在动态sql中插入记录时如何处理撇号

How to handle apostophee while inserting record in dynamic sal

这里是存储的示例 procedure.Real SP 包含 35 个 parameter.Out 只有一个参数 Message 可以包含撇号。如果我尝试将这样的记录插入 table,让 error.How 来处理它。

 Create Procedure ProcInsertRecord
    @Name varchar(30),
    @mobile_no varchar(30),
    @message varchar(30),
    @Address varchar(30),
    @Designation varchar(30)
    as
    begin

    set @SQL = 'INSERT INTO ['+@table+'](Name,Mobile,Message,Address,Designation) values ('''+@Name +''' , '+@mobile_no+' , '''+@message+''','''+@Address+''','''@Designation+''')

    sp_helptext @SQL 

    end

您丢失了一些字符。

尝试:

DECLARE
    @Name VARCHAR(30) = 'Name',
    @mobile_no VARCHAR(30) = 'Mobile',
    @message VARCHAR(30) = 'Message',
    @Address VARCHAR(30) = 'Adress',
    @Designation VARCHAR(30) = 'Designation',
    @SQL VARCHAR(1000) = 'SQL',
    @table VARCHAR(100) = 'table'


SET @SQL = 'INSERT INTO [' + @table + '](Name,Mobile,Message,Address,Designation) values (''' + @Name + ''' , ' + @mobile_no + ' , ''' + @message + ''',''' + @Address + ''',''' + @Designation + ''')'

PRINT @SQL

正如我在评论中所写,对于这个问题,您当前的代码存在几个问题 - 首先,它表明存在数据库设计问题。

除了查找和系统版本控制的 tables,创建多个具有相同结构且仅按名称延迟的 tables 通常表明您正在将元数据与数据 - 意味着数据从您的 tables 内容泄漏到您的 tables 结构。

应消除 table 名称中的差异,并且应将 table 合并为一个 table,包含(至少)一列以表明差异.

尽管如此,有些情况下您根本无法更改数据库结构 - 如果是这种情况,您仍然需要动态 SQL 解决方案。

您的代码的第二个问题是它容易受到 SQL 注入攻击。
如果有人要使用该过程并将最后一个参数值设置为 'bob'');DROP TABLE Students;--'(或其他一些 table 名称),您的代码将无法阻止该攻击。

此外,您在问题中显示的代码并未在任何地方声明 @table 变量,但我只是假设您在编写问题时错过了这一点。

您抱怨的一个问题(无法使用包含撇号 (') 的字符串作为变量)将在您使用 [ 将过程更改为安全执行后得到解决=14=].

只有一条规则可以创建注入安全的动态 SQL,而且它实际上非常简单 - 参数化你可以的,白名单你不能的。

因此,如果我必须为此插入创建一个动态 SQL 存储过程 - 这就是我要做的(另请注意代码中的注释):

CREATE PROCEDURE ProcInsertRecord
    @Name varchar(30),
    @mobile_no varchar(30),
    @message varchar(30),
    @Address varchar(30),
    @Designation varchar(30),
    @table sysname
    AS
    BEGIN
        -- declare your variables. Don't use nvarchar(max) unless you have to. 
        DECLARE @Sql nvarchar(4000), 
                @LineBreak nchar(2) = NCHAR(13) + NCHAR(10), 
                @ParamDefinition nvarchar(4000);

        -- White list your table name: making sure not only that it exists,
        -- but also it has all the columns you are using in your insert statement.
        IF EXISTS(
            SELECT 1
            FROM InformationSchema.Columns
            WHERE Column_Name IN('Name', 'Mobile', 'Message', 'Address', 'Designation')
            AND Table_Name = @table
            GROUP BY Table_Name
            -- This is usually count(distinct xxx), but column names are unique in a table.
            HAVING COUNT(Column_Name) = 5 
        )

        BEGIN
            -- QUOTENAME protects your query from breaking on table names with spaces or other "strage" chars in their name.
            -- Use line breaks to make your query readable.
            SET @SQL = N'INSERT INTO '+ QUOTENAME(@table) +' (Name, Mobile, Message, Address, Designation) '+ @LineBreak + 
                       N'VALUES (@Name, @mobile_no, @message, @Address, @Designation)'

            -- When dealing with dynamic SQL, print is your best friend.
            PRINT @SQL 

            SET @ParamDefinition = 
                N'@Name varchar(30),
                  @mobile_no varchar(30),
                  @message varchar(30),
                  @Address varchar(30),
                  @Designation varchar(30)'

            -- Unremark only when print displays a valid SQL.
            --EXEC sp_ExecuteSql 
            --     @SQL, 
            --     @ParamDefinition, 
            --     @Name, @mobile_no, @message, @Address, @Designation

        END
    END