在过程中使用动态SQL将数据插入架构表

时间:2019-03-18 11:34:15

标签: sql-server tsql stored-procedures dynamic-sql

我希望你们一切都好。

我一直在研究一个项目,该项目需要存储有关我的大学的数据,包括ID号,姓名,联系方式等。

在创建一个能够将数据插入到指定的schema.table_name中的存储过程时,我有些困难。该过程必须能够允许EXEC命令指定要将数据插入到哪个架构中。对于所有14个模式,table_name都将保持不变。以下代码示例是我想出的,但似乎不起作用:

CREATE PROCEDURE AddStudent_proc(@campus varchar(50), @StudentID numeric(4,0), @Name varchar(50), @Surname varchar(50), @ID_numeric numeric(13,0), @Address varchar(100))
AS
BEGIN
    DECLARE @dynamic varchar(MAX)
    SET @dynamic = 'INSERT INTO ['+quotename(@campus)+'].Student_tbl(
    StudentID,
    Name,
    Surname,
    ID_numeric,
    Address
    )
    VALUES('+quotename(@StudentID)+','+quotename(@Name)+','+quotename(@Surname)+','+quotename(@ID_numeric)+','+quotename(@Address)+');'
    EXEC (@dynamic);
END
GO

可以找到我的整个结构 here

感谢您对这个主题的任何帮助,因为我对SQL整体还是很陌生。

谢谢。

1 个答案:

答案 0 :(得分:3)

您不需要使用quotename来存储数据-正如函数名称所暗示的那样,应将其与名称(也称为标识符)一起使用。
另外,当您使用quotename时,它会在接收到的值周围加上[],因此没有必要再次添加它们(代码中的['+quotename(@campus)+'])。

我建议对您现在的程序进行三处改进:

  1. @campus的数据类型更改为sysname-这是SQL Server用于所有标识符的nvarchar(128) not null的特殊数据类型同义词。
  2. 将架构名称列入白名单。
    这是防止SQL注入攻击的重要更改。
    所有无法参数化的内容都必须列入白名单。
  3. 使用sp_ExecuteSql代替EXEC

这将导致更好的存储过程,因为它消除了SQL Injection的威胁:

CREATE PROCEDURE AddStudent_proc(
    @campus sysname, 
    @StudentID numeric(4,0), 
    @Name varchar(50), 
    @Surname varchar(50), 
    @ID_numeric numeric(13,0), 
    @Address varchar(100)
)
AS
BEGIN

    IF EXISTS(
        SELECT 1
        FROM Sys.Schemas
        WHERE name = @campus
    )
    BEGIN

    DECLARE @dynamic nvarchar(4000), 
            @paramDefinition nvarchar(4000)


        SELECT @dynamic = N'INSERT INTO '+ quotename(@campus) + N'.Student_tbl (
            StudentID,
            Name,
            Surname,
            ID_numeric,
            Address
        )
        VALUES(@StudentID, @Name, @Surname, @ID_numeric, @Address)',
        @paramDefinition = 
          N'@StudentID numeric(4,0), 
            @Name varchar(50), 
            @Surname varchar(50), 
            @ID_numeric numeric(13,0), 
            @Address varchar(100)'

        EXEC sp_executeSql @dynamic, @paramDefinition, @StudentID, @Name, @Surname, @ID_numeric, @Address;
    END
END
GO