使用动态SQL复制具有新id值的表记录

时间:2017-10-26 01:07:23

标签: sql-server sql-server-2008 dynamic-sql

我有一个申请,要求用户可以"复制"一个记录。这将复制表中的记录以及任何子表中的关联记录。

我将使用触发器执行存储过程来执行复制。我面临的问题是我想增加复制记录的ID字段,这也是子表中的FK。 ID字段不是标准格式,因此使用增量不会起作用。为了使这个面向未来,我打算使用动态SQL来为每个表提取列,这样如果我向其中一个表添加一个新字段,我就不需要修改代码。客户端的系统管理员也可以通过GUI向表中添加列,但他们无法访问SQL后端,因此他们需要联系我们修改代码(不理想)。

示例:

Declare @ColumnNames varchar(2000)
Declare @BLDGCODE char(4)
set @BLDGCODE = '001'

select @ColumnNames = COALESCE(@ColumnNames + ', ', '') + COLUMN_NAME
from 
    INFORMATION_SCHEMA.COLUMNS
where 
    TABLE_NAME='FMB0'
Declare @DynSqlStatement varchar(max);
set @DynSqlStatement = 'Insert into dbo.FMB0('+ @ColumnNames + ') 
select * from dbo.FMB0 where BLDGCODE= ' + cast(@BLDGCODE as char(4));

print(@DynSqlStatement);

这解决了将新列添加到其中一个表的问题。但是,如何增加ID(本例中为BLDGCODE)。我唯一的解决方案是按名称编写列,这样我可以增加ID,还是有一个我忽略的功能?

希望这是有道理的。我充其量只是一个中级SQL用户,如果有明显的解决方案,请原谅天真的。

更新

所以我决定使用#temp表来保存已更改的记录,修改那里的id,然后从#temp表插回主表。这很有效,只有一个例外。我收到以下错误:

专栏" FLOORID _"无法修改,因为它是计算列或是UNION运算符的结果。

以下是我的存储过程。我已经调查了STUFF方法,但不确定在哪里插入该代码。 Using STUFF with calculated column。我现在回想以为我需要专门为带有计算列的一个表调用列,如果我们添加一个新字段,我只需要修改这个存储过程。有没有其他想法?

ALTER PROCEDURE [dbo].[LDAC_BLDGCOPY]
    @BLDGCODE CHAR(4)
AS
BEGIN
    SET NOCOUNT ON;

    --COPY BUILDING RECORD
    BEGIN
        DECLARE @ColumnNamesB0 VARCHAR(2000);

        SELECT *
        INTO #TEMPB0
        FROM FMB0
        WHERE BLDGCODE = @BLDGCODE;

        UPDATE #TEMPB0
        SET BLDGCODE = CONVERT(CHAR(4), (CAST((@BLDGCODE) AS INT) + 
100)),
            auto_key = dbo.GetAutoKey(),
            BLDGCOPY = 0;

        SELECT @ColumnNamesB0 = COALESCE(@ColumnNamesB0+', ', 
'')+COLUMN_NAME
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'FMB0';

        DECLARE @DynSqlStatementB0 VARCHAR(MAX);
        SET @DynSqlStatementB0 = 'Insert into dbo.FMB0('+@ColumnNamesB0+') 
select * from #TEMPB0';

        EXEC (@DynSqlStatementB0);
     END;

    --COPY FLOOR RECORDS
    BEGIN
        DECLARE @ColumnNamesL0 VARCHAR(2000);
        --DECLARE @Val INT = 
RTRIM(CONVERT(CHAR(10),CAST(LEFT(@BL_KEY,LEN(RTRIM(@BL_KEY))-2)+1 as 
INT)))+'01

        SELECT *
        INTO #TEMPL0
        FROM FML0
        WHERE BLDGCODE = @BLDGCODE;

        UPDATE #TEMPL0
        SET BLDGCODE = CONVERT(CHAR(4), (CAST((@BLDGCODE) AS INT) + 
100)),
            auto_key = dbo.GetAutoKey();

        UPDATE #TEMPL0
        SET FLOORID_ = auto_key;

        SELECT @ColumnNamesL0 = COALESCE(@ColumnNamesL0+', ', 
'')+COLUMN_NAME
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'FML0';

        DECLARE @DynSqlStatementL0 VARCHAR(MAX);
        SET @DynSqlStatementL0 = 'Insert into dbo.FML0('+@ColumnNamesL0+') 
select * from #TEMPL0';
         EXEC (@DynSqlStatementL0);
     END;

--COPY ROOM RECORDS
     BEGIN
         DECLARE @ColumnNamesA0 VARCHAR(2000);
--DECLARE @Val INT = 
RTRIM(CONVERT(CHAR(10),CAST(LEFT(@BL_KEY,LEN(RTRIM(@BL_KEY))-2)+1 as 
INT)))+'01

         SELECT *
         INTO #TEMPA0
         FROM FMA0
         WHERE BLDGCODE = @BLDGCODE;
         UPDATE #TEMPA0
           SET
               BLDGCODE = CONVERT(CHAR(4), (CAST((@BLDGCODE) AS INT) + 
100)),
               auto_key = dbo.GetAutoKey(),
               FLOORID = #TEMPL0.FLOORID_
         FROM #TEMPA0
              INNER JOIN #TEMPL0 ON CONVERT(CHAR(4), (CAST((@BLDGCODE) AS 
INT) + 100)) = #TEMPL0.BLDGCODE;
         SELECT @ColumnNamesA0 = COALESCE(@ColumnNamesA0+', ', 
'')+COLUMN_NAME
         FROM INFORMATION_SCHEMA.COLUMNS
         WHERE TABLE_NAME = 'FMA0';
         DECLARE @DynSqlStatementA0 VARCHAR(MAX);
         SET @DynSqlStatementA0 = 'Insert into dbo.FMA0('+@ColumnNamesA0+') 
select * from #TEMPA0';
         EXEC (@DynSqlStatementA0);
         DROP TABLE #TEMPB0;
         DROP TABLE #TEMPL0;
         DROP TABLE #TEMPA0;
     END;
 END;

0 个答案:

没有答案