在动态 sql 中处理单引号的正确方法?

Posted

技术标签:

【中文标题】在动态 sql 中处理单引号的正确方法?【英文标题】:Proper way to handle single quote in dynamic sql? 【发布时间】:2019-12-07 18:43:02 【问题描述】:

我在下面有一个动态的sql查询来创建一个函数,我用4x单引号替换了单引号,但是它不起作用。

EXEC(
'
CREATE  OR ALTER FUNCTION dbo.fnGetNumberFromPCN
(
    @PCN VARCHAR(50)
)
RETURNS BIGINT
AS
BEGIN

        --Init
        DECLARE @Number BIGINT = NULL

        --Get
        SELECT @Number = CASE WHEN PATINDEX(''''%[^0-9]%'''',STUFF(V.YourString,1,PI.I-1,'''''''')) > 0 
                                 THEN CONVERT(BIGINT, SUBSTRING(V.YourString,PI.I,PATINDEX''''%[^0-9]%'''',STUFF(V.YourString,1,PI.I-1,''''''''))-1))
                                 ELSE 0
                            END
        FROM (VALUES(@PCN),(@PCN))V(YourString)
             CROSS APPLY (VALUES(PATINDEX''''%[1-9]'''', V.YourString)))PI(I)

        --Finally
        RETURN @Number
END
')
GO

【问题讨论】:

【参考方案1】:

只需检查生成的 SQL,您就会发现问题:

declare @sql varchar(max) = '
CREATE  OR ALTER FUNCTION dbo.fnGetNumberFromPCN
(
    @PCN VARCHAR(50)
)
RETURNS BIGINT
AS
BEGIN

        --Init
        DECLARE @Number BIGINT = NULL

        --Get
        SELECT @Number = CASE WHEN PATINDEX(''''%[^0-9]%'''',STUFF(V.YourString,1,PI.I-1,'''''''')) > 0 
                                 THEN CONVERT(BIGINT, SUBSTRING(V.YourString,PI.I,PATINDEX''''%[^0-9]%'''',STUFF(V.YourString,1,PI.I-1,''''''''))-1))
                                 ELSE 0
                            END
        FROM (VALUES(@PCN),(@PCN))V(YourString)
             CROSS APPLY (VALUES(PATINDEX''''%[1-9]'''', V.YourString)))PI(I)

        --Finally
        RETURN @Number
END
'
print @sql
--exec (@sql)

输出

CREATE  OR ALTER FUNCTION dbo.fnGetNumberFromPCN
(
    @PCN VARCHAR(50)
)
RETURNS BIGINT
AS
BEGIN

        --Init
        DECLARE @Number BIGINT = NULL

        --Get
        SELECT @Number = CASE WHEN PATINDEX(''%[^0-9]%'',STUFF(V.YourString,1,PI.I-1,'''')) > 0 
                                 THEN CONVERT(BIGINT, SUBSTRING(V.YourString,PI.I,PATINDEX''%[^0-9]%'',STUFF(V.YourString,1,PI.I-1,''''))-1))
                                 ELSE 0
                            END
        FROM (VALUES(@PCN),(@PCN))V(YourString)
             CROSS APPLY (VALUES(PATINDEX''%[1-9]'', V.YourString)))PI(I)

        --Finally
        RETURN @Number
END

失败了

Msg 102, Level 15, State 1, Procedure fnGetNumberFromPCN, Line 15 [Batch Start Line 0]
Incorrect syntax near ''.

【讨论】:

我也使用了 2x 单引号。但还是失败了。 是的,但有不同的错误或错误位置,您可以用相同的方式查找和修复。 谢谢。我现在明白了。 @DavidBrowne-Microsoft 请添加对此处字符串或特殊引用的支持:feedback.azure.com/forums/908035-sql-server/suggestions/… 随着引入对新语言的支持 - Python/R/Java(外部脚本),这应该是必须的。此外,它将简化大量动态 SQL - 就像在这个例子中一样。数 ' 并将它们加倍有时会让人头疼,而且容易出错。

以上是关于在动态 sql 中处理单引号的正确方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何插入包含单引号的字符串

sqlserver中怎么去掉单引号

如何在 Oracle SQL 中处理单引号

SQL 中单引号 和一些特殊字符的处理

oracle怎样将动态sql插到字段中去单引号里面包含单引号报错

sql语句插入的数据中含有单引号怎么办?