如何在不指定列名的情况下插入?

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 并添加一列来指定每一行所指的事物的类型。