2013-03-14 110 views
14

我试图执行以下语句,以逃避单引号(即使用两个单引号):逃逸单引号在SQL Server

declare @year varchar(max) 
set @year = '111,11'; 
exec ('SELECT * FROM SplitValues(' + @year + ','','')'); 

我甚至试过用char(39)代替报价:

declare @year varchar(max) 
set @year = '111,11'; 
exec ('SELECT * FROM SplitValues(' + @year + ',' + char(39) + ',' + char(39) + ')'); 

但它没有帮助。这是我在这个网站上找到的唯一两个解决方案。任何帮助?

这是简化的查询清理你所有的问题:

declare @year varchar(max) 
set @year = '111,11'; 
SELECT * FROM SplitValues(@year , ',') 

我要做到这一点,但使用动态查询。

+0

为什么你需要在这里使用EXEC? – Bridge 2013-03-14 12:19:39

+0

这是因为我现在工作的查询非常复杂,无法在此处发布。这只是我想要做的一瞥。 – Saksham 2013-03-14 12:24:23

+0

可能的重复* [在SQL Server中替换单引号](http://stackoverflow.com/questions/1440733/replace-single-quotes-in-sql-server)*。 – 2016-01-25 14:50:13

回答

23

一句忠告。测试动态脚本时,首先显示它而不是执行它。这样,您将能够完全看到EXEC声明中的情况。

现在到了这个问题。您应该记住,您未将变量改为SplitValues,而是将该变量的值连接到脚本中。由于值为varchar,因此应将其与其周围的引号连接起来。他们的缺席是唯一的问题。

第二个参数(逗号)周围的引号在两种情况下均正确转义。所以,仅仅使用两种方法来添加引号的第一个参数:

DECLARE @year varchar(max), @sql varchar(max); 
SET @year = '111,11'; 
SET @sql = 'SELECT * FROM SplitValues(''' + @year + ''','','')'; 
SELECT @sql; 
  • 使用CHAR(39)

    • 引号的重复

      DECLARE @year varchar(max), @sql varchar(max); 
      SET @year = '111,11'; 
      SET @sql = 'SELECT * FROM SplitValues(' + CHAR(39) + @year + CHAR(39) + ',' + CHAR(39) + ',' + CHAR(39) + ')'; 
      SELECT @sql; 
      

    显然,第一种方法更加紧凑,但正如我所说的,两者都很好,因为this SQL Fiddle demo清楚地表明。

    但是,请注意,如果您原谅双关语,您可以轻松地摆脱此问题。您可以使用EXEC sp_executesql而不是EXEC(),它允许您使用参数。下面是重写使用sp_executesql相同的脚本:

    DECLARE @year varchar(max), @delim char(1); 
    SET @year = '111,11'; 
    SET @delim = ','; 
    EXEC sp_executesql 
        N'SELECT * FROM SplitValues(@year_param,@delim_param)', 
        N'@year_param varchar(max), @delim_param char(1)', 
        @year,@delim; 
    

    正如你所看到的,没有必要担心转义引号:SQL Server会正确替换值,而不是你的麻烦。

  • +0

    对不起,我不确定我懂不懂。你在这里观察到的问题是什么? – 2013-11-26 12:57:51

    +0

    我想在您的初始声明中指出您应该打印命令而不是执行验证的讽刺,但sp_executesql不会给您打印语句而不执行它的选项。如果有办法,也许你应该展示它。 我想打印出来的声明是有限的实用程序,因为它比替代品更具可读性。 – 2013-11-27 00:58:14

    +0

    如果动态查询不包含任何名称参数化(在这种情况下没有任何名称参数),则不需要将许多部分粘在一起构建。所以是的,使用一个变量来存储查询只是在/之前打印它而不是它的执行似乎没有多大价值。 – 2013-11-27 04:41:18

    8

    只需键入单引号两次:

    select 'that''s it' 
    
    +0

    这是我尝试的第一件事,你可以在我的发布解决方案中看到。 – Saksham 2013-03-14 12:18:48

    +1

    不完全。 '+ char(39)+'会​​给你三个引号,而你需要四个引号。让我们试试整个语句: exec('SELECT * FROM SplitValues('''+ @year +''','''','''')'); – 2013-03-14 12:22:19

    2

    好了......你想利用这个字符串:

    SELECT * FROM SplitValues(@year , ',') 
    

    ,使它像这样的字符串:

    'SELECT * FROM SplitValues('111,11' , '','')' 
    

    所以,你的最终代码是:

    declare @year varchar(max), @sql varchar(max) 
    set @year = '111,11'; 
    set @sql = 'SELECT * FROM SplitValues(''' + @year + ''' , '''','''')' 
    
    select @sql 
    

    其实,最后选择你会用exec()来代替。不过,你可能应该使用sp_sqlexecute这样的东西,因为你可以使用参数化查询。