如何正确将CTE临时表查询结果作为值插入SQL目标表?
错误原因
你的语句执行失败有两个核心问题:
- CTE定义语法错误:声明多个链式CTE时,仅第一个CTE前需要加
WITH关键字,后续CTE直接写定义即可,重复加WITH会直接触发语法报错。另外标准SQL中字符串常量需要用单引号包裹,你代码里用双引号包裹"john"、"smith"的写法,在PostgreSQL等多数数据库中会被识别为标识符(字段/表名),也可能触发对象不存在的报错。 - CTE引用逻辑错误:
VALUES子句无法直接引用CTE返回的字段,CTE是临时结果集不是会话变量,作用域仅对WITH块后紧跟的查询语句生效,必须通过SELECT语句从CTE中取值,不能直接在值列表里写CTE的字段名。
正确实现方案
两个CTE都通过LIMIT 1限制了仅返回1行1列的结果,你可以通过交叉连接关联两个CTE,得到刚好1行包含两个目标id的记录,拼接UTC当前时间后插入即可,代码如下:
WITH temp_table_1 AS ( SELECT id FROM table_A WHERE fname = 'john' LIMIT 1 ), temp_table_2 AS ( SELECT id FROM table_B WHERE lname = 'smith' LIMIT 1 ) INSERT INTO table_c (col_1, col_2, created_at) SELECT t1.id, t2.id, CURRENT_TIMESTAMP AT TIME ZONE 'UTC' FROM temp_table_1 t1 CROSS JOIN temp_table_2 t2;
补充说明
- 因为两个CTE都只返回单行数据,交叉连接不会产生多行笛卡尔积,最终只会向
table_c插入1条符合要求的记录。 - 如果你用的是MySQL这类不原生支持
AT TIME ZONE语法的数据库,可以直接用内置函数UTC_TIMESTAMP()替换时间取值部分,效果一致。 - 不想写连接的话,也可以用标量子查询直接取值,效果完全相同:
WITH temp_table_1 AS ( SELECT id FROM table_A WHERE fname = 'john' LIMIT 1 ), temp_table_2 AS ( SELECT id FROM table_B WHERE lname = 'smith' LIMIT 1 ) INSERT INTO table_c (col_1, col_2, created_at) SELECT (SELECT id FROM temp_table_1), (SELECT id FROM temp_table_2), CURRENT_TIMESTAMP AT TIME ZONE 'UTC';
内容的提问来源于stack exchange,提问作者shahram kalantari
相关产品推荐
相关产品推荐

