我有一个申请,要求用户可以"复制"一个记录。这将复制表中的记录以及任何子表中的关联记录。
我将使用触发器执行存储过程来执行复制。我面临的问题是我想增加复制记录的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;