如何批量执行由查询返回的多条INSERT SQL语句?
如何一次性运行SQL查询生成的多条INSERT语句
当然可以,具体实现取决于你使用的数据库和脚本工具,以下是几种常见数据库的实操方法:
MySQL/MariaDB
- 导出到SQL文件再执行:
先修改查询,把生成的INSERT语句导出到本地文件:
然后用命令行执行这个文件:WITH abc AS (SELECT a1, a2 FROM tableX), xyz AS (SELECT b1, b2 FROM tableY) SELECT CONCAT('INSERT INTO tableZ (col1) VALUES (', QUOTE(abc.a1), ');') INTO OUTFILE '/tmp/inserts.sql' FROM abc JOIN xyz ON abc.a1 = xyz.b1;
(注:mysql -u 用户名 -p 数据库名 < /tmp/inserts.sqlQUOTE()函数用来转义单引号等特殊字符,避免语法错误)
PostgreSQL
- 方法一:导出文件执行
接着用psql执行:WITH abc AS (SELECT a1, a2 FROM tableX), xyz AS (SELECT b1, b2 FROM tableY) SELECT format('INSERT INTO tableZ (col1) VALUES (%L);', abc.a1) FROM abc JOIN xyz ON abc.a1 = xyz.b1 COPY TO '/tmp/inserts.sql';psql -U 用户名 -d 数据库名 -f /tmp/inserts.sql - 方法二:直接在PL/SQL块中执行
如果数据量不大,可直接用DO块动态执行生成的语句:DO $$ DECLARE rec record; BEGIN FOR rec IN WITH abc AS (SELECT a1, a2 FROM tableX), xyz AS (SELECT b1, b2 FROM tableY) SELECT format('INSERT INTO tableZ (col1) VALUES (%L);', abc.a1) AS stmt FROM abc JOIN xyz ON abc.a1 = xyz.b1 LOOP EXECUTE rec.stmt; END LOOP; END $$;
Oracle
- 导出到文件执行:
需要先创建目录对象并授权,然后用UTL_FILE包导出语句:
之后用sqlplus执行文件:DECLARE v_file UTL_FILE.FILE_TYPE; v_stmt VARCHAR2(1000); CURSOR c_inserts IS WITH abc AS (SELECT a1, a2 FROM tableX), xyz AS (SELECT b1, b2 FROM tableY) SELECT 'INSERT INTO tableZ (col1) VALUES (' || REPLACE(abc.a1, '''', '''''') || ');' AS stmt FROM abc JOIN xyz ON abc.a1 = xyz.b1; BEGIN v_file := UTL_FILE.FOPEN('SQL_DIR', 'inserts.sql', 'W'); FOR rec IN c_inserts LOOP UTL_FILE.PUT_LINE(v_file, rec.stmt); END LOOP; UTL_FILE.FCLOSE(v_file); END; /sqlplus 用户名/密码@数据库 @/path/to/inserts.sql - 方法二:PL/SQL块直接执行
同样可以用EXECUTE IMMEDIATE循环执行每条生成的INSERT语句,逻辑和上面的导出块类似,只是把写入文件换成执行语句。
注意事项
- 必须处理特殊字符(比如单引号),否则会导致INSERT语句语法错误,不同数据库有对应的转义函数或方法,上面的示例已经包含了处理方式。
- 批量执行前建议先手动测试1-2条生成的语句,确认语法正确后再批量运行。
内容的提问来源于stack exchange,提问作者fiddle
相关产品推荐
相关产品推荐

