具有唯一索引的SQL克隆记录

时间:2020-03-06 14:53:06  来源:igfitidea点击:

有没有一种干净的方法来克隆SQL中具有索引(自动增量)的记录。我想克隆除索引外的所有字段。我目前必须枚举每个字段,并在插入选择中使用它,而我宁愿不明确列出所有字段,因为它们可能随时间而变化。

解决方案

除非我们想进入动态SQL,否则不可以。既然我们写的是"干净",我就不做。

编辑:由于他要求一个动态的SQL示例,我将对此进行介绍。我目前尚未连接到任何数据库,因此这是我的首要任务,几乎可以肯定需要修订。但希望它能抓住事物的精神:

-- Get list of columns in table
SELECT INTO #t
EXEC sp_columns @table_name = N'TargetTable'

-- Create a comma-delimited string excluding the identity column
DECLARE @cols varchar(MAX)
SELECT @cols = COALESCE(@cols+',' ,'') + COLUMN_NAME FROM #t WHERE COLUMN_NAME <> 'id'

-- Construct dynamic SQL statement
DECLARE @sql varchar(MAX)
SET @sql = 'INSERT INTO TargetTable (' + @cols + ') ' +
    'SELECT ' + @cols + ' FROM TargetTable WHERE SomeCondition'

PRINT @sql -- for debugging
EXEC(@sql)

我们可以创建一个插入触发器来执行此操作,但是,我们将失去使用显式ID进行插入的功能。相反,它将始终使用序列中的值。

我想不出一种简单明了的方法,但是从我们所提问题中的几个问题中,我会担心基础体系结构。也许我们有绝对正当的理由想要这样做,但是通常我们想要避免数据库中的重复项,而不是使它们更容易引起。同样,显式命名列通常是一个好主意。如果要链接到外部代码,请确保在添加新列时不会中断该链接。如果我们不是这样(听起来我们可能不在这种情况下),我仍然希望列出这些列,因为这迫使我查看更改/新列的影响,即使只是查看更改/新列的效果也是如此。代码,并确定添加新列不是问题。

我们可以创建一个触发器来为我们执行此操作。为了确保触发器仅适用于克隆,我们可以创建一个单独的用户名CLONE并使用它登录。或者,甚至更好的是,如果DBMS支持它,则创建一个名为CLONE的角色,任何用户都可以使用该角色登录并进行克隆。触发代码将类似于:

if (CURRENT_ROLE = 'CLONE') then
   new.ID = assign new id from generator/sequence

当然,我们只能将该角色授予允许克隆记录的用户。

DROP TABLE #tmp_MyTable

SELECT * INTO #tmp_MyTable
FROM MyTable
WHERE MyIndentID = 165

ALTER TABLE #tmp_MyTable
DROP Column MyIndentID

INSERT INTO MyTable
SELECT * 
FROM #tmp_MyTable