拥有多个表格(例如两个):
|PEOPLE_ID|PEOPLE_NAME|PEOPLE_ACCOUNT|OTHER_NULLABLE_COLUMNS|
|001 |"Andrea" |NULL |OTHER_NULLABLE_COLUMNS|
|002 |"..." |NULL |OTHER_NULLABLE_COLUMNS|
和
|PET_ID|PET_NAME|PET_OWNER|OTHER_NULLABLE_COLUMNS|
|001 |"Fido" |NULL |OTHER_NULLABLE_COLUMNS|
|002 |"..." |NULL |OTHER_NULLABLE_COLUMNS|
然后我需要一个通用存储过程来插入任何传递表名(pet,people)以及id和name作为参数的表。
exec sp_inserttottable 'people', '456', 'Gustavo'
exec sp_inserttottable 'pet', '852', 'Scooby'
但是在存储过程的定义中我不能这样做:
CREATE PROCEDURE sp_inserttottable
@tableName nvarchar(50),
@codeToInsert nvarchar(4),
@detailToInsert nvarchar(100)
AS
DECLARE @cmd AS NVARCHAR(max)
SET @cmd = 'INSERT INTO ' + @tableName + ' VALUES(' + @codeToInsert + ',' + @detailToInsert + ' )' + ' '
EXEC sp_executesql @cmd
它给我一个错误,我需要像这样指定列名:
'INSERT INTO ' + @tableNames + ' (PEOPLE_ID, PEOPLE_NAME) VALUES(' + @codeToInsert + ',' + @detailToInsert + ' )' + ' '
但如果我这样做,程序就不能通用了。
如果我可以这样做,按列顺序放置值:
'INSERT INTO ' + @tableNames + ' (1, 2) VALUES(' + @codeToInsert + ',' + @detailToInsert + ' )' + ' '
如何实现这一目标?
首先使用DEFAULT KEYWORD
CREATE PROCEDURE sp_InsertTableType
@tableNames nvarchar(50),
@codeToInsert nvarchar(4),
@detailToInsert nvarchar(100)
AS
DECLARE @cmd AS NVARCHAR(max)
SET @cmd = 'INSERT INTO ' + @tableNames + ' VALUES(' + @codeToInsert + ',' + @detailToInsert + ', DEFAULT)' + ' ';
--SET @cmd = 'INSERT INTO TTCODI_NACI_UPDATE(CODE, DESCRI) VALUES(' + @codeToInsert + ',' + @detailToInsert + ')' + ' '
EXEC sp_executesql @cmd
然后我打电话:
exec sp_InsertTableType 'TTCODI_NACI', '1000', 'kuwaiti'
它引发了我:Invalid column name '%.*ls'.
第二种选择:
创建视图:
create view TTCODI_NACI_UPDATE
as
SELECT CO_NACI AS CODE, DE_NACI AS DESCRI
, DE_ABRE_NACI AS ABRE
FROM TTCODI_NACI;
更改存储过程:
CREATE PROCEDURE sp_InsertTableType
@tableNames nvarchar(50),
@codeToInsert nvarchar(4),
@detailToInsert nvarchar(100)
AS
DECLARE @cmd AS NVARCHAR(max)
--SET @cmd = 'INSERT INTO ' + @tableNames + ' VALUES(' + @codeToInsert + ',' + @detailToInsert + ', DEFAULT)' + ' ';
SET @cmd = 'INSERT INTO TTCODI_NACI_UPDATE(CODE, DESCRI) VALUES('
+ @codeToInsert + ',' + @detailToInsert + ')' + ' '
EXEC sp_executesql @cmd
我打电话的时候:
exec sp_InsertTableType 'TTCODI_NACI', '1000', 'kuwaiti'
它引发了我:Update or insert of view or function '%.*ls' failed because it contains a derived or constant field.
答案 0 :(得分:3)
这是解决您问题的方法,但我并不是真的提倡它。你的表是针对不同的实体的,所以我不太确定通用存储过程是个好主意。
一种解决方案是使用DEFAULT
关键字:
SET @cmd = 'INSERT INTO ' + @tableName + ' VALUES(DEFAULT, ' + @codeToInsert + ',' + @detailToInsert + ' )' + ' ';
哦,我真的不喜欢那样。这意味着插入取决于列在表中定义的顺序 - 并且对于添加新列并弄乱此代码的任何人都有祸害,远离新列的创建。
我更熟悉的另一个解决方案是创建视图,例如:
create v_people_for_update as
select people_id as id, people_name as name, people_account as account
from people;
然后,插入视图:
SET @cmd = 'INSERT INTO ' + @viewName(name, account) + ' VALUES(, ' + @codeToInsert + ',' + @detailToInsert + ' )' + ' ';
这至少可以让你指定列(一件好事),并且可以命名视图集合,因此很明显这个存储过程正在处理它们。
但是,如果您有具有类似结构的表,那么您应该将它们组合到一个表中,并且不要使用动态SQL在不同表中进行选择。只需使用一个表并添加一列,指定每行引用的事物的类型。