给sql存储过程传递参数报错,错误为(字符串后的引号不完整)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了给sql存储过程传递参数报错,错误为(字符串后的引号不完整)相关的知识,希望对你有一定的参考价值。

create PROC Get_Data1
(
@sTable NVARCHAR(100)
,@sWhere NVARCHAR(1000)
)
AS

DECLARE @sql VARCHAR(4000)
SET @sql = ' EXEC master..xp_cmdshell ''bcp "select * from' + @sTable
+ @sWhere + '"'
+ ' queryout C:\authors.xls -c -q -S"192.168.10.12" -U"sa" -P"123"'
EXEC(@sql)

exec Get_Data1 ' Table_BaLiBao ',' where 时间<''2014-11-27 11:00:00'' and 时间>''2014-11-27 05:00:00'''

字符串 '" queryout C:\authors.xls -c -q -S"192.168.10.12" -U"sa" -P"123"' 后的引号不完整。

参考技术A 修改一下第二个参数的时间格式试试
问题应该出在这里追问

修改好多次了 ,都失败了,请高手帮忙啊

如何通过参数将大于 200 个字符的字符串传递给存储过程

【中文标题】如何通过参数将大于 200 个字符的字符串传递给存储过程【英文标题】:How to pass a string larger than 200 character to a stored procedure via param 【发布时间】:2017-06-12 00:39:18 【问题描述】:

我遇到了一个问题,在我的代码中,我必须对数据表中存在的所有文章进行求和请求,我将所有文章 ID 连接到一个字符串中,例如“a1,a2,a3”,这是假定的上班。

但是我有大 ID 和大约 150 篇文章,所以我尝试传递给存储过程的字符串大约是 1300 个字符,当它进入存储过程时会被截断为 200 个字符。

你知道有什么解决方案可以在没有 SQL Server 截断这个字符串的情况下将大字符串传递给存储过程吗?

如果能帮到你,我可以在这里写C#代码或SQL存储过程。

这是存储过程:

ALTER PROCEDURE [dbo].[GetChargePetrin]
-- Add the parameters for the stored procedure here
@articlesList varchar(MAX)
AS

BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

        SELECT 
        CAST(SUM(CAST(Qa01 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa1',
        CAST(SUM(CAST(Qa02 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa2',
        CAST(SUM(CAST(Qa03 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa3',
        CAST(SUM(CAST(Qa04 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa4',
        CAST(SUM(CAST(Qa05 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa5',
        CAST(SUM(CAST(Qa06 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa6',
        CAST(SUM(CAST(Qa07 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa7',
        CAST(SUM(CAST(Qa08 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa8',
        CAST(SUM(CAST(Qa09 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa9',
        CAST(SUM(CAST(Qa10 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa10',
        CAST(SUM(CAST(Qa11 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa11',
        CAST(SUM(CAST(Qa12 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa12',
        CAST(SUM(CAST(Qa13 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa13',
        CAST(SUM(CAST(Qa14 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa14',
        CAST(SUM(CAST(Qa15 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa15',
        CAST(SUM(CAST(Qa16 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa16',
        CAST(SUM(CAST(Qa17 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa17',
        CAST(SUM(CAST(Qa18 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa18',
        CAST(SUM(CAST(Qa19 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa19',
        CAST(SUM(CAST(Qa20 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa20',
        CAST(SUM(CAST(Qa21 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa21',
        CAST(SUM(CAST(Qa22 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa22',
        CAST(SUM(CAST(Qa23 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa23',
        CAST(SUM(CAST(Qa24 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa24',
        CAST(SUM(CAST(Qa25 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa25',
        CAST(SUM(CAST(Qa26 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa26',
        CAST(SUM(CAST(Qa27 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa27',
        CAST(SUM(CAST(Qa28 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa28',
        CAST(SUM(CAST(Qa29 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa29',
        CAST(SUM(CAST(Qa30 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa30',
        CAST(SUM(CAST(Qa31 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa31',
        CAST(SUM(CAST(Qa32 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa32',
        CAST(SUM(CAST(Qa33 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa33',
        CAST(SUM(CAST(Qa34 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa34',
        CAST(SUM(CAST(Qa35 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa35',
        CAST(SUM(CAST(Qa36 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa36',
        CAST(SUM(CAST(Qa37 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa37',
        CAST(SUM(CAST(Qa38 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa38',
        CAST(SUM(CAST(Qa39 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa39',
        CAST(SUM(CAST(Qa40 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa40',
        CAST(SUM(CAST(Qa41 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa41',
        CAST(SUM(CAST(Qa42 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa42',
        CAST(SUM(CAST(Qa43 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa43',
        CAST(SUM(CAST(Qa44 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa44',
        CAST(SUM(CAST(Qa45 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa45',
        CAST(SUM(CAST(Qa46 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa46',
        CAST(SUM(CAST(Qa47 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa47',
        CAST(SUM(CAST(Qa48 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa48',
        CAST(SUM(CAST(Qa49 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa49',
        CAST(SUM(CAST(Qa50 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa50',
        CAST(SUM(CAST(Qa51 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa51',
        CAST(SUM(CAST(Qa52 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa52',
        CAST(SUM(CAST(Qa53 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa53',
        CAST(SUM(CAST(Qa54 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa54',
        CAST(SUM(CAST(Qa55 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa55',
        CAST(SUM(CAST(Qa56 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa56',
        CAST(SUM(CAST(Qa57 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa57',
        CAST(SUM(CAST(Qa58 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa58',
        CAST(SUM(CAST(Qa59 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa59',
        CAST(SUM(CAST(Qa60 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa60'
        FROM [PDP_TTP].[dbo].[PDP] p
        inner join [PDP_TTP].[dbo].[Articles] a ON a.Division=p.Division and a.Code_article=p.Code_article
        WHERE CAST(a.CO_UQB_PET AS INT) >0 and a.Code_article IN( SELECT Id = Item FROM dbo.SplitInts(@articlesList, ','));

END

【问题讨论】:

我们需要查看您的存储过程。例如,param 很有可能是 varchar(200),然后答案就很明显了! 您应该查看表值参数,而不是传递分隔字符串。当您传递分隔字符串时,您要么必须拆分它们,要么通过动态 sql 暴露 sql 注入漏洞。 所以存储过程并没有限制长度,也许 C# 为该参数指定了 200 的长度(所有帐户都这样做)。也许您可以从调试代码开始,而不是让我们猜测! ....所以通过消除过程,您认为它可能是什么? (提示:见我之前的评论) 在包含示例查询的最后一次更新中,我敦促您规范化此表。 Qa1-60 尖叫着可怕的设计,并通过重复列违反了 1NF。考虑一下添加 Qa70-90 会有多痛苦。您必须为每个查询添加 20 个新列。如果这被正确规范化,您将添加新行,并且您的任何查询都不必更改。 【参考方案1】:

我同意 Sean Lange 的评论,并建议使用表值参数而不是发送字符串并在 sql 中解析它 为此,您需要在 sql server 中创建用户定义的表类型:

CREATE TYPE dbo.ArticleIds as table
(
    Id varchar(10) -- should be the same as Code_article definition!
)
GO

然后将其用作

ALTER PROCEDURE [dbo].[GetChargePetrin]
-- Add the parameters for the stored procedure here
    @articlesList dbo.ArticleIds readonly -- Must be readonly!
AS

BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

        SELECT 
        CAST(SUM(CAST(Qa01 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa1',
        CAST(SUM(CAST(Qa02 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa2',
        -- ... more of the same
        CAST(SUM(CAST(Qa60 AS INT) /CAST(a.CO_UQB_PET AS INT)) AS varchar) as 'qa60'
        FROM [PDP_TTP].[dbo].[PDP] p
        INNER JOIN [PDP_TTP].[dbo].[Articles] a ON a.Division=p.Division AND a.Code_article=p.Code_article
        INNER JOIN @articlesList al ON a.Code_article = al.Id
        WHERE CAST(a.CO_UQB_PET AS INT) > 0 

END

要使用 ADO.NET 从 c# 执行带有表值参数的存储过程,您需要发送一个类型为 SqlDbType.Structured 的参数并传递一个 DataTable 作为它的值。

【讨论】:

我会使用你的解决方案。起初我没有想到我将来会有超过 500 篇文章,所以我需要你的解决方案来处理这么多文章。谢谢 我刚刚完成了您的解决方案的实施和测试,效果很好,感谢您花时间向我展示带有 sql 示例的最佳解决方案,您拯救了我的一天!【参考方案2】:

我的方法中有p.Size = 200; 添加 Sql 参数,我必须将其更改为 p.Size = 8000; 并且它正在工作。

感谢大家的帮助!

【讨论】:

这将一直有效,直到您超过 8,000 个字符。构建此过程对于可伸缩性、性能和可维护性会更好,因此无论您拥有多少值都无关紧要。这是表值参数真正擅长的地方。 msdn.microsoft.com/en-us/library/bb510489.aspx

以上是关于给sql存储过程传递参数报错,错误为(字符串后的引号不完整)的主要内容,如果未能解决你的问题,请参考以下文章

将用户定义表中的日期值传递给 SQL Server 2008 存储过程

为一个 SQL 参数传递多个值

在 azure synapse 存储过程中将表名作为参数传递时将查询结果分配给变量

使用ado.net将多个SQL表值参数传递到单个存储过程

我有个SQL in 使用参数传递怎么弄?

将 xml 字符串参数传递给 SQL Server 存储过程