如何在不指定列名的情况下插入?
How to insert without specifying the column name?
有很多 table(例如两个):
|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|
然后我需要一个通用存储过程来插入任何 table 并传递 table(宠物、人)的名称以及 id 和名称作为参数。
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 + ' )' + ' '
如何实现?
(更新)应用@Gordon Linoff
的解决方案
首先使用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.
这是解决你的问题的方法,但我并不真正提倡它。您的 table 用于不同的实体,因此我不太确定通用存储过程是个好主意。
一种解决方案是使用 DEFAULT
关键字:
SET @cmd = 'INSERT INTO ' + @tableName + ' VALUES(DEFAULT, ' + @codeToInsert + ',' + @detailToInsert + ' )' + ' ';
哦,我真的不喜欢那样。这意味着插入取决于列在 table 中定义的顺序 - 任何添加新列并弄乱此代码的人都会有祸了,远离新列的创建。
另一种让我感觉更舒服的解决方案table 是创建视图,例如:
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 + ' )' + ' ';
这至少让您可以指定列(一件好事)并且可以命名视图集合,因此很明显这个存储过程正在处理它们。
但是,如果您有 table 具有如此相似的结构,那么您可能应该将它们组合成一个 table 并放弃使用动态 SQL 进行选择的想法不同的 table。只需使用一个 table 并添加一列来指定每一行所指的事物的类型。
有很多 table(例如两个):
|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|
然后我需要一个通用存储过程来插入任何 table 并传递 table(宠物、人)的名称以及 id 和名称作为参数。
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 + ' )' + ' '
如何实现?
(更新)应用@Gordon Linoff
的解决方案首先使用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.
这是解决你的问题的方法,但我并不真正提倡它。您的 table 用于不同的实体,因此我不太确定通用存储过程是个好主意。
一种解决方案是使用 DEFAULT
关键字:
SET @cmd = 'INSERT INTO ' + @tableName + ' VALUES(DEFAULT, ' + @codeToInsert + ',' + @detailToInsert + ' )' + ' ';
哦,我真的不喜欢那样。这意味着插入取决于列在 table 中定义的顺序 - 任何添加新列并弄乱此代码的人都会有祸了,远离新列的创建。
另一种让我感觉更舒服的解决方案table 是创建视图,例如:
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 + ' )' + ' ';
这至少让您可以指定列(一件好事)并且可以命名视图集合,因此很明显这个存储过程正在处理它们。
但是,如果您有 table 具有如此相似的结构,那么您可能应该将它们组合成一个 table 并放弃使用动态 SQL 进行选择的想法不同的 table。只需使用一个 table 并添加一列来指定每一行所指的事物的类型。