SQL Server问题。 做的时候
INSERT INTO T1 SELECT (C1, C2) FROM T2
我不想指定T1
的列名,因为它们与T2
是否可以这样做?
目前我收到错误
Msg 213,Level 16,State 1,Line 1
列名或提供的值与表定义不匹配。
答案 0 :(得分:18)
始终在INSERT和SELECT投影中都使用显式列。即使你不想,你应该:
INSERT INTO T1 (C1, c2)
SELECT C1, C2 FROM T2
答案 1 :(得分:13)
是的,您可以省略插入的表的字段名称,并且可以使用select *来获取表中的所有字段,但我不建议使用此方法。
如果省略字段名称,则字段按位置匹配,而不是按名称匹配。如果字段的顺序不完全相同,则会混淆。通常,您应该避免依赖表的确切布局,以最大程度地降低表中更改破坏查询的风险。
答案 2 :(得分:3)
如果T1
和T2
完全匹配,您有两个选择。您可以select
T2
insert into T1
的所有列insert
,也可以为select
语句提供列列表。
即使您执行insert
MSSQL提供的列标题,{{1}}语句也不会使用该信息来匹配列。
答案 3 :(得分:1)
为什么不简单
INSERT INTO t1
SELECT * FROM T2
答案 4 :(得分:0)
如果您担心列名称,您可以随时为它们添加别名:
INSERT INTO T1 (C1, c2)
SELECT C1 AS C1_ALIAS, C2 AS C2_ALIAS FROM T2
或者,更简洁:
INSERT INTO T1 (C1, c2)
SELECT C1 C1_ALIAS, C2 C2_ALIAS FROM T2
虽然我不能真正想到为什么人们会想要这样一个简单的例子
答案 5 :(得分:0)
首先选择这个sql,从sql结果中选择你的表行并更改目标或源表名。如果表具有相同的列(不需要相同的顺序),它将起作用。
with xparams as ( select (select user from dual) "OWNER", '' "ADDSTRTOFROMTABLENAME" from dual ) ,t1 as ( SELECT dbat.table_name from dba_tables dbat, xparams where dbat.owner = xparams.OWNER ) ,t1c1 as ( SELECT utcs.table_name , LISTAGG(utcs.column_name,',') within group (order by utcs.column_name) "COLS" from USER_TAB_COLUMNS utcs, t1 where utcs.table_name = t1.table_name group by utcs.table_name ) ,res1 as ( SELECT 'insert into '|| t1c1.table_name || ' ( '|| t1c1.COLS ||') select '|| t1c1.COLS || ' from ' || t1c1.table_name||xparams.ADDSTRTOFROMTABLENAME ||';' "RES" from t1c1, xparams order by t1c1.table_name ) select * from res1
答案 6 :(得分:0)
其他答案是好的,但没有解释为什么不好用:
INSERT INTO T1
SELECT * FROM T2
在评论中,OP讨论了使用更安全的方法指定列时的代码重复:
INSERT INTO T1 (C1, c2)
SELECT C1, C2 FROM T2
但是,如果您不确定,您将依赖始终匹配的列数以及期望的列顺序。如果更改其中一个表以添加一个逻辑,则该逻辑将中断 柱。
此外,您还会遇到无声错误的麻烦。如果您使用具有相同列数但位置不同的表:
CREATE TABLE tab1 (col1 int, col2 string);
CREATE TABLE tab2 (col1 string, col2 int);
INSERT INTO tab1 values(1, 'aaa');
INSERT INTO TABLE tab2 select * FROM tab1;
然后,您可能希望您进行了复制,以使tab1和tab2相同。我想要的是:
+-------------------+-------------------+
| tab2.col1 | tab2.col2 |
+-------------------+-------------------+
| 1 | aaa |
+-------------------+-------------------+
但是它将根据列位置加载并转换数据,所以我得到的是:
+-------------------+-------------------+
| tab2.col1 | tab2.col2 |
+-------------------+-------------------+
| 1 | NULL |
+-------------------+-------------------+
发生的事情是它无法将字符串转换为int,因此将其设置为NULL。它可以将int转换为字符串“ 1”,而不再是数字类型。
即使列确实匹配,任何人都可以做:
ALTER TABLE tab1 ADD COLUMNS (col3 string COMMENT 'a new column');
此后,未指定列的查询将中断,说明两个表中的列数不匹配。它将不再能够将数据移到tab2中。
这意味着安全的做法是使用SQL明确:
INSERT INTO T1 (C1, c2)
SELECT C1, C2 FROM T2
如果有人只是想快速获取表的副本,则某些SQL引擎支持
CREATE TABLE tab3 AS SELECT * FROM tab1;
在这种情况下,请确保键入列是浪费时间,并且如果有人在克隆之前在tab1中添加列,则显式将无法克隆新列。所有反例显示的是,仅编程经验法则没有绝对的规则。如果您不希望在运行时出现静默错误,而又不想在有人添加新功能时发现错误,则SQL(以及任何其他具有隐式转换的松散类型的语言)的经验法则应尽可能具体。
答案 7 :(得分:-1)
参考如下:
INSERT INTO NEWTABLENAME COL1[,COL2,..COLN]
SELECT COL1[,COL2,..COLN] FROM THE EXISTINGTABLENAME