我在动态 sql 中找不到错误

Posted

技术标签:

【中文标题】我在动态 sql 中找不到错误【英文标题】:I can't find the error within my dynamic sql 【发布时间】:2015-07-07 05:07:19 【问题描述】:

我对下面的存储过程代码有问题,它运行顺利,但是当我尝试执行存储过程时,它会抛出这个错误:

消息 241,级别 16,状态 1,过程 ACC_ARAP_DOC_LIST,第 27 行 从字符串转换日期和/或时间时转换失败。

我猜是@DATE_FROM@DATE_TO?从外部声明为DATETIME 格式。在执行存储过程时,我尝试了2001-01-0101-01-2001 格式。两者都抛出了同样的错误。 我正在使用 SQL Server 2014 Management Studio。

那么有谁知道问题出在哪里?

ALTER PROCEDURE [dbo].[ACC_ARAP_DOC_LIST]
    @DATE_FROM DATETIME,
    @DATE_TO DATETIME,
    @DOC_TYPE_GROUP CHAR(20)='DIV',
    @FILTER_CONDITION NVARCHAR(4000)='',
    @RESULT_MODE NVARCHAR(30)= NULL --'DOC_SUM'
AS
BEGIN 
    DECLARE @SQL NVARCHAR(4000) --Select
    DECLARE @SQL2 NVARCHAR(4000)
    DECLARE @WHERE NVARCHAR(4000)
    DECLARE @PARAMETER NVARCHAR(1000)
    DECLARE @GROUP_BY NVARCHAR(4000)
    DECLARE @GROUP_ORDER_BY NVARCHAR(4000)
    DECLARE @ORDER_BY NVARCHAR(4000)
    DECLARE @SQL_SUM_START NVARCHAR(4000)
    DECLARE @SQL_SUM_END NVARCHAR(4000)

    SET @SQL = 'SELECT * FROM (SELECT j1.journal_no, j1.acc_date, j1.partner_code, j1.term_code, j1.due_date, j1.ref_no1, j1.ref_no2,
                                j1.description,j1.sales_person,j1.pay_remark ,j1.amount,j1.acc_amount,j1.currency, j1.match_acc_amount, p1.name as partner_name
                                FROM acc_journal j1 
                                INNER JOIN acc_journal_groupcfg g1 ON g1.group_type=''LST'' AND g1.doc_type_group=' + @DOC_TYPE_GROUP + ' AND g1.doc_type=j1.doc_type
                                LEFT OUTER JOIN partner p1 ON j1.partner_code=p1.partner_code 
                                LEFT OUTER JOIN partner_acc p2 ON p1.partner_id=p2.partner_id) as sql1'
    SET @WHERE = ' WHERE acc_date>=' + @DATE_FROM +' AND acc_date<=' + @DATE_TO + ' ' +
       (CASE WHEN ISNULL(@filter_condition,'')<>'' 
                    THEN 'AND '+@filter_condition ELSE '' END)
    SET @ORDER_BY = ' ORDER BY journal_no'

    SET @PARAMETER = '@DATE_FROM DATETIME,@DATE_TO DATETIME,@RESULT_MODE NVARCHAR(30)=''DOC_SUM'',@DOC_TYPE_GROUP CHAR(20)'


    SET @SQL = @SQL + @WHERE + @ORDER_BY

    IF @RESULT_MODE = 'DOC_SUM'
    BEGIN
        SET @SQL = 'SELECT * FROM (SELECT j1.journal_no, j1.acc_date, j1.partner_code as Code, j1.term_code, j1.due_date, j1.ref_no1, j1.ref_no2,
                                j1.description,j1.sales_person,j1.pay_remark ,j1.amount,j1.acc_amount,j1.currency, j1.match_acc_amount, p1.name as Name
                                FROM acc_journal j1 
                                INNER JOIN acc_journal_groupcfg g1 ON g1.group_type=''LST'' AND g1.doc_type_group=' +@DOC_TYPE_GROUP +'AND g1.doc_type=j1.doc_type
                                LEFT OUTER JOIN partner p1 ON j1.partner_code=p1.partner_code 
                                LEFT OUTER JOIN partner_acc p2 ON p1.partner_id=p2.partner_id) as sql1'
        SET @SQL_SUM_START= 'SELECT Code, Name, COUNT(*) as Count, SUM(acc_amount) as Total_Amount FROM ('
        SET @SQL_SUM_END= ') as SQLsum'

        SET @GROUP_BY = ' GROUP BY Code, Name'
        SET @GROUP_ORDER_BY = ' ORDER BY Code, Name'
        SET @SQL2 = @SQL_SUM_START + @SQL +@SQL_SUM_END + @GROUP_BY + @GROUP_ORDER_BY
    END

    SET @SQL = 'SELECT * FROM (SELECT j1.journal_no, j1.acc_date, j1.partner_code, j1.term_code, j1.due_date, j1.ref_no1, j1.ref_no2,
                                j1.description,j1.sales_person,j1.pay_remark ,j1.amount,j1.acc_amount,j1.currency, j1.match_acc_amount, p1.name as partner_name
                                FROM acc_journal j1 
                                INNER JOIN acc_journal_groupcfg g1 ON g1.group_type=''LST'' AND g1.doc_type_group=' + @DOC_TYPE_GROUP +'AND g1.doc_type=j1.doc_type
                                LEFT OUTER JOIN partner p1 ON j1.partner_code=p1.partner_code 
                                LEFT OUTER JOIN partner_acc p2 ON p1.partner_id=p2.partner_id) as sql1'
    SET @SQL = @SQL + @WHERE + @ORDER_BY

    EXEC sp_executesql @SQL, @SQL2, @PARAMETER,
    @DOC_TYPE_GROUP=@DOC_TYPE_GROUP,
    @DATE_FROM=@DATE_FROM,
    @DATE_TO=@DATE_TO
END

【问题讨论】:

您使用的 dbms 以及 Date_from 和 date_to 中的值是什么 尝试 ISO-8601 日期格式:YYYYMMDD - 没有破折号,没有空格 - 什么都没有。如果您只需要日期(没有时间) - 请改用 DATE 数据类型! 我用的是MSSQL,值通常是'2014-01-01'和'2015-12-31'。 @marc_s 我收到此错误:消息 402,级别 16,状态 1,过程 ACC_ARAP_DOC_LIST,第 32 行数据类型 varchar 和 date 在 add 运算符中不兼容。 【参考方案1】:

您需要将 DATETIME 参数转换为合适的字符串,以便将它们构建为动态 SQL 字符串。例如,而不是:

... 
SET @WHERE = ' WHERE acc_date>=' + @DATE_FROM +' AND acc_date<=' + @DATE_TO + ' ' +...

使用(注意额外的引号)

...
SET @WHERE = ' WHERE acc_date>=''' + CONVERT(nvarchar(30), @DATE_FROM, 120) 
+ ''' AND acc_date<=''' + CONVERT(nvarchar(30), @DATE_TO, 120) + ''' ' + ...

另外,您需要在构建的字符串中引用 @DOC_TYPE_GROUP 参数,如下所示(再次注意额外的引号):

...AND g1.doc_type_group=''' + @DOC_TYPE_GROUP + ''' AND g1.doc_type=...

我建议您使用PRINT @SQL 而不是SP_EXEC SQL @SQL 来帮助您进行调试。

【讨论】:

@DATE_FROM='2001-01-01' and @DATE_TO='2015-12-31' 然后我得到了这个错误:Msg 102, Level 15, State 1, Line 8 Incorrect syntax near ' 00'。【参考方案2】:

在你的存储过程中应该连接两个变量@DATE_FROM@DATE_TO。它必须是转换varchar。像这样

SET @WHERE = ' WHERE acc_date>=' +convert(varchar(25), @DATE_FROM )+' AND acc_date<=' +convert(varchar(25), @DATE_TO) + ' ' +

删除此代码

 (CASE WHEN ISNULL(@filter_condition,'')<>'' 
                    THEN 'AND '+@filter_condition ELSE '' END)

替换

if(isnull(@FILTER_CONDITION,'')!='')
     SET @WHERE=@WHERE+'AND '+@filter_condition

【讨论】:

Msg 102,级别 15,状态 1,第 8 行 '1' 附近的语法不正确。 添加调用存储过程数据 EXEC return_value = [dbo].[ACC_ARAP_DOC_LIST] DATE_FROM = N'2001-01-01',DATE_TO = N'2015-12-31',DOC_TYPE_GROUP = N'DIV',RESULT_MODE = NULL --N'DOC_SUM' SELECT '返回值' = return_value GO 只看这部分 -> DATE_FROM = N'2001-01-01', DATE_TO = N'2015-12-31'【参考方案3】:

您需要将@date_from@date_to 中的值转换为NVARCHAR。之后,您需要在它周围设置括号。

替换这个:

SET @WHERE = ' WHERE acc_date>=' + @DATE_FROM +' AND acc_date<=' + @DATE_TO + '

有了这个:

SET @WHERE = ' WHERE acc_date>=''' + CONVERT(nvarchar(max),@DATE_FROM) +''' AND acc_date<=''' + CONVERT(nvarchar(max),@DATE_TO) + '''

顺便说一句,你也应该提高你的@sql 值,以避免一些截止错误。 您将nvarchar(4000) 用于@sql。而是尝试使用nvarchar(max)。如果您的 SQL 可能会变得冗长,它可能会避免错误。

【讨论】:

以上是关于我在动态 sql 中找不到错误的主要内容,如果未能解决你的问题,请参考以下文章

pear DB 错误:在 windows 7 apache 服务器中找不到扩展名 sql server

在 Tomcat 中找不到适合 jdbc 错误的驱动程序

java.sql.SQLSyntaxErrorException:用户缺少特权或在 ubuntu 中找不到对象

我创建了一个 SQL Server 函数。现在我在 SSMS 中找不到它

使用 ssis 包在 SQL Server 代理作业中找不到存储过程错误

我在 Laravel 迁移基础视图/表中找不到奇怪的错误 1146