SQL SELECT INSERT INTO 生成唯一标识符

11

我正在尝试选择一个数据表,并将这个数据插入到另一个具有相似列名的文件中(它基本上是重复的数据)。当前语法如下:

INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT similiarId, similiarId2, similiarCol1, similiarCol2  
FROM TABLE2

我的问题是生成唯一的键字段(声明为整数)以用于新插入的记录。我不能使用table2的键作为table1已经存在数据并将在重复键值上出错。

我无法更改表架构,这些是自定义ID列,不是由数据库自动生成的。


3
保持密钥的原始值重要吗? - heximal
不要从表2中插入相似的ID,让表1为行生成新的ID。 - rs.
表1中的ID是自定义ID吗?如果不是,你可以在ID上使用IDENTITY,它会自动为你创建ID。 - yoozz
你可以在table1中使用自增量,不需要像rs说的那样插入similarId。 - vijay
1
你不能只是在table1中添加一个identity列并将新列设置为主键吗?然后你只需插入而不需要新的主键列,identity会自动生成你的键。 - JamieSee
一些演示数据突出问题会很有帮助。 - Tim Lehner
10个回答

11

table1的id字段是否有自动递增?如果是,您是否可以在插入时省略similiarId并让自动递增处理唯一键?

INSERT INTO TABLE1 (id2, col1, col2) SELECT similiarId2, similiarCol1, similiarCol2
FROM TABLE2

这是一个自定义的ID,不是由数据库自动递增/生成的。 - jrb

10
根据您的要求,您需要按以下方式执行查询:
INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT (ROW_NUMBER( ) OVER ( ORDER BY ID ASC )) 
+ (SELECT MAX(id) FROM TABLE1) AS similiarId
, similiarId2, similiarCol1, similiarCol2  
FROM TABLE2

我在这里做了什么:
添加了ROW_NUMBER(),它将从1开始,所以还添加了MAX()函数来获取目标表的ID。

为更好的解释,请参见此SQLFiddle


5
我不确定我是否正确理解您的意思: 您想从TABLE2中复制所有数据,但要确保TABLE2.similiarId尚未在TABLE1.id中,也许这是您问题的解决方案:
DECLARE @idmax INT
SELECT @idmax = MAX(id) FROM TABLE1

INSERT INTO TABLE1 (id, id2, col1, col2)
SELECT similiarId + @idmax, similiarId2, similiarCol1, similiarCol2  
FROM TABLE2

现在,插入操作不会因为主键冲突而失败,因为每个插入的id都将大于已经存在的id。

+1。只要不经常在大表上进行(使用max可能会有性能问题),并且更改similiarID“键”是可以接受的(没有引用问题),我建议采用这种方法。否则,他们可能需要自己实现序列或使用带有identity的临时表。 - Tim Lehner

3
如果将id字段定义为自动递增,并在插入语句中省略该字段,则SQL将从可用池中生成唯一的id。

这不是自动识别字段。 - jrb

2
在SQL Server中,我们有ROW_NUMBER函数,如果我理解正确,以下代码将实现您需要的功能:
    INSERT INTO TABLE1 (id, id2, col1, col2)
    SELECT (ROW_NUMBER( ) OVER ( ORDER BY similiarId2 ASC )) + 6 AS similiarId, 
similiarId2, similiarCol1, similiarCol2  
    FROM TABLE2

ROW_NUMBER函数可以返回每行的编号,您可以添加一个“魔术值”使这些值与TABLE1的当前最大ID不同。假设您当前的最大ID为6,则将ROW_NUMBER的每个结果加上6将给您7、8、9等。这样您就不会有相同的主键值了。

我向谷歌搜索了一下,它告诉我Sybase也有ROW_NUMBER函数(http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.sqlanywhere.12.0.1/dbusage/ug-olap-s-51258147.html),所以您可以尝试使用它。


小心这个问题...他们没有明确指出他们正在使用 Sybase SQLAnywhere,他们只是说“Sybase”,所以很有可能他们指的是 Sybase ASE,据我所知它没有 ROW_NUMBER 函数? - sybkar
@sybkar,感谢您的评论。在这种情况下,我建议采用Jarek Bielicki指出的方法,或者如果user1464435想要保证其顺序新ID,则使用带有标识列的临时表作为中间表。 - Fabio

2
如果您想制作一个完全相同的表格,为什么不使用(简单粗暴的)Select INTO 方法呢?
SELECT * INTO TABLE2
FROM TABLE1 

希望这能帮到你。

1

如果table1不是自定义ID,则将table1的ID设置为IDENTITY。

或者

在table1中创建新的主键并使其成为IDENTITY,您可以保留先前的ID以相同的格式(但不是主键)。


在这里更新数据库模式不是一个选项,需要一个函数或SQL查询来完成此操作,因为它是一个自定义ID。 - jrb

1
你最好的选择可能是在Table2上添加一个额外的列来存储Table1.Id。这样你就可以保留两组键。
(如果你正在进行数据合并,保留Table1.Id可能对任何仍然引用Table1.Id的外键很重要 - 然后你需要“修复”引用Table1.Id的表中的外键,现在需要引用表2中适用的键)。

这里不是更新数据库模式的选项,需要一个函数或SQL查询来完成此操作,因为它是自定义ID。 - jrb

0
如果你有一个很大的范围,并且想要快速创建而不关心ID:
以CONCAT为例子
INSERT INTO session(SELECT CONCAT("3000", id) as id, cookieid FROM `session2`)

但你也可以使用 REPLACE


0
如果您需要第二个表与第一个表保持类似的值,则不要在第二个表上应用“自动增量”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接