关键字“FOR”XML 附近的语法不正确

Posted

技术标签:

【中文标题】关键字“FOR”XML 附近的语法不正确【英文标题】:Incorrect syntax near the keyword 'FOR' XML 【发布时间】:2017-07-21 06:33:26 【问题描述】:

我得到了错误

关键字“FOR”附近的语法不正确

当我将'+@ SirketNo+' 写入点时。

我找不到错误。

错误:

消息 156,第 15 级,状态 1,第 110 行 关键字“FOR”附近的语法不正确

消息 102,第 15 级,状态 1,第 125 行 ',' 附近的语法不正确

消息 102,第 15 级,状态 1,第 137 行 ',' 附近的语法不正确

我的代码:

DECLARE @SirketNo AS NVARCHAR(3)= '427', 
        @AliciAdreslerinDepartmani AS NVARCHAR(MAX) = 'MuhasebeMuduru',
        @BilgiAliciAdreslerinDepartmani AS NVARCHAR(MAX) = 'Mudur',
        @GizliAliciAdreslerinDepartmani AS NVARCHAR(MAX) = 'FinansKoordinatoru'', ''FinansSorumlusu'', ''Developer';

DECLARE @SqlQuery AS NVARCHAR(max) = N'
BEGIN
    DECLARE @KacGunOnce INT= 13, @xml NVARCHAR(MAX), @KasaBakiye NVARCHAR(MAX), @AliciAdresler VARCHAR(MAX), @BilgiAliciAdresler VARCHAR(MAX), @GizliBilgiAliciAdresler VARCHAR(MAX), @vucut NVARCHAR(MAX), @Baslik VARCHAR(100)= '''', @CreatedBy VARCHAR(100)= '''', @Mesaj VARCHAR(250)= '''', @IsYeriNo SMALLINT;
    DECLARE @mad TABLE
    (logicalref              INT IDENTITY(1, 1),
     IsYeriNo                SMALLINT,
     KasaKodu                VARCHAR(17),
     KasaAdi                 VARCHAR(51),
     AlıcıAdresler           NVARCHAR(MAX),
     BilgiAlıcıAdresler      NVARCHAR(MAX),
     GizliBilgiAlıcıAdresler NVARCHAR(MAX)
    );
END; --Değişkenleri ve değişken tabloyu oluştur 

BEGIN
    INSERT INTO @mad
    (IsYeriNo,
     KasaKodu,
     KasaAdi
    )
           SELECT DISTINCT
                  ksl.BRANCH,
                  lk.CODE,
                  lk.NAME
           FROM LG_'+@SirketNo+'_01_KSLINES AS KSL WITH (NOLOCK)
                JOIN L_CAPIUSER AS U WITH (NOLOCK) ON U.NR LIKE KSL.CAPIBLOCK_CREATEDBY
                JOIN LG_'+@SirketNo+'_KSCARD AS lk ON lk.LOGICALREF = ksl.CARDREF
           WHERE ksl.SIGN = 1
                 AND ksl.AMOUNT >= 300
                 AND CONVERT(VARCHAR(10), ksl.DATE_, 104) = CONVERT(VARCHAR(10), GETDATE() - @KacGunOnce, 104);
END; --Değişken tabloya verileri insert et



BEGIN
    --Döngü için değişken atamaları
    DECLARE @s INT= 1, @d INT=
    (
        SELECT COUNT(logicalref)
        FROM @mad
    );

    --Döngü
    WHILE @d >= @s
        BEGIN

            /**** DÖNGÜ BAŞLANGIÇ ****/



            BEGIN
                SELECT @KasaBakiye =
                (
                    SELECT KasaKodu
                    FROM @mad
                    WHERE logicalref = @s
                )+'' kodlu kasanın güncel bakiyesi: ''+FORMAT(SUM(CASHTOT.DEBIT - CASHTOT.CREDIT), ''c2'', ''tr-TR'')
                FROM LG_'+@SirketNo+'_KSCARD AS CASHC WITH (NOLOCK),
                     LG_'+@SirketNo+'_01_CSHTOTS AS CASHTOT WITH (NOLOCK)
                WHERE CASHC.CODE LIKE
                (
                    SELECT KasaKodu
                    FROM @mad
                    WHERE logicalref = @s
                )
                      AND CASHTOT.CARDREF = CASHC.LOGICALREF
                      AND CASHTOT.TOTTYPE = 1
                      AND CASHTOT.DAY_ >= 0
                      AND CASHTOT.DAY_ <= 365;
            END; --Kasa Bakiyesini değişkene ata



            BEGIN
                -- İş yerini değişkene ata
                SELECT @IsYeriNo = IsYeriNo
                FROM @mad
                WHERE logicalref = @s;
            END; -- İş yerini değişkene ata;



            BEGIN --Kasa hareketlerini html formatında XMLe dönüştür      
                SET @xml = CAST(
                               (
                                   SELECT f.DATE_ AS ''td'',
                                          '''',
                                          f.FICHENO AS ''td'',
                                          '''',
                                          f.TRCODE AS ''td'',
                                          '''',
                                          f.CUSTTITLE AS ''td'',
                                          '''',
                                          f.LINEEXP AS ''td'',
                                          '''',
                                          f.AMOUNT AS ''td'',
                                          '''',
                                          f.REPORTRATE AS ''td'',
                                          '''',
                                          f.REPORTNET AS ''td'',
                                          '''',
                                          f.SPECODE AS ''td'',
                                          '''',
                                          f.CYPHCODE AS ''td'',
                                          '''',
                                          f.BRANCH AS ''td'',
                                          '''',
                                          f.NAME AS ''td'',
                                          ''''
                                   FROM
                                   (
                                       SELECT ksl.DATE_,
                                              KSL.FICHENO,
                                              CASE TRCODE
                                                  WHEN 11
                                                  THEN ''CARİ HESAP TAHSİLAT''
                                                  WHEN 12
                                                  THEN ''CARİ İŞLEM''
                                                  WHEN 21
                                                  THEN ''BANKA İŞLEMİ''
                                                  WHEN 22
                                                  THEN ''BANKA İŞLEMİ''
                                                  WHEN 31
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 32
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 33
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 34
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 35
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 36
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 37
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 38
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 39
                                                  THEN ''FATURA İŞLEMİ''
                                                  WHEN 61
                                                  THEN ''ÇEK-SENET İŞLEMİ''
                                                  WHEN 62
                                                  THEN ''ÇEK-SENET İŞLEMİ''
                                                  WHEN 63
                                                  THEN ''ÇEK-SENET İŞLEMİ''
                                                  WHEN 64
                                                  THEN ''ÇEK-SENET İŞLEMİ''
                                                  WHEN 71
                                                  THEN ''KASA İŞLEMİ''
                                                  WHEN 72
                                                  THEN ''KASA İŞLEMİ''
                                                  WHEN 73
                                                  THEN ''KASA İŞLEMİ''
                                                  WHEN 74
                                                  THEN ''KASA İŞLEMİ''
                                                  ELSE ''TANIMSIZ İŞLEM''
                                              END AS ''TRCODE'',
                                              KSL.CUSTTITLE,
                                              KSL.LINEEXP,
                                              FORMAT(AMOUNT, ''c2'', ''tr-TR'') AS ''AMOUNT'',
                                              CAST(REPORTRATE AS MONEY) AS ''REPORTRATE'',
                                              CAST(REPORTNET AS MONEY) AS ''REPORTNET'',
                                              KSL.SPECODE,
                                              KSL.CYPHCODE,
                                              KSL.BRANCH,
                                              U.NAME
                                       FROM LG_'+@SirketNo+'_01_KSLINES AS KSL WITH (NOLOCK) /**************************************/
                                            JOIN L_CAPIUSER AS U WITH (NOLOCK) ON U.NR LIKE KSL.CAPIBLOCK_CREATEDBY
                                            JOIN LG_427_KSCARD AS lk ON lk.LOGICALREF = ksl.CARDREF
                                       WHERE ksl.SIGN = 1
                                             AND ksl.AMOUNT >= 300
                                             AND CONVERT(VARCHAR(10), ksl.DATE_, 104) = CONVERT(VARCHAR(10), GETDATE() - @KacGunOnce, 104)
                                             AND ksl.BRANCH =
                                       (
                                           SELECT IsYeriNo
                                           FROM @mad
                                           WHERE logicalref = @s
                                       )
                                             AND lk.CODE =
                                       (
                                           SELECT KasaKodu
                                           FROM @mad
                                           WHERE logicalref = @s
                                       )
                                   ) AS f
                                   FOR XML PATH(''tr''), ELEMENTS
                               ) AS NVARCHAR(max));
            END; --Kasa hareketlerini HTML formatında XML''e dönüştür  



            BEGIN
                UPDATE @mad
                  SET
                      [AlıcıAdresler] = ISNULL(
                                              (
                                                  SELECT TOP 1 REPLACE(
                                                                      (
                                                                          SELECT RTRIM(MAIL) [data()]
                                                                          FROM mad.dbo.Kullanicilar k
                                                                          WHERE k.SIRKET = ''427''
                                                                                AND IS_YERI = @IsYeriNo
                                                                                AND LEN(MAIL) > 0
                                                                                AND DEPERTMAN IN('''+@AliciAdreslerinDepartmani+''')
                                                                          FOR XML PATH('''')
                                                                      ), '' '', ''; '') AS BIRLESIK
                                              ), ''''),
                      [BilgiAlıcıAdresler] = ISNULL(
                                                   (
                                                       SELECT TOP 1 REPLACE(
                                                                           (
                                                                               SELECT RTRIM(MAIL) [data()]
                                                                               FROM mad.dbo.Kullanicilar k
                                                                               WHERE k.SIRKET = ''427''
                                                                                     AND IS_YERI = @IsYeriNo
                                                                                     AND LEN(MAIL) > 0
                                                                                     AND DEPERTMAN IN('''+@BilgiAliciAdreslerinDepartmani+''')
                                                                               FOR XML PATH('''')
                                                                           ), '' '', ''; '') AS BIRLESIK
                                                   ), ''''),
                      [GizliBilgiAlıcıAdresler] = ISNULL(
                                                        (
                                                            SELECT TOP 1 REPLACE(
                                                                                (
                                                                                    SELECT RTRIM(MAIL) [data()]
                                                                                    FROM mad.dbo.Kullanicilar k
                                                                                    WHERE k.SIRKET = ''427''
                                                                                          AND LEN(MAIL) > 0
                                                                                          AND DEPERTMAN IN('''+@GizliAliciAdreslerinDepartmani+''')
                                                                                    FOR XML PATH('''')
                                                                                ), '' '', ''; '') AS BIRLESIK
                                                        ), '''')
                WHERE IsYeriNo = @IsYeriNo;
            END; -- Değişken tabloya mail adreslerini update et



            BEGIN
                UPDATE @mad
                  SET
                      [AlıcıAdresler] = [BilgiAlıcıAdresler]
                WHERE [AlıcıAdresler] = '''';
            END; -- Değişken tabloda alici adresi boş olanlara bilgideki adresleri alici olarak ekle



            BEGIN
                SET @Baslik = '''';
                SET @Mesaj = '''';
                SET @vucut = '''';
                SELECT @Baslik+=CONVERT( NVARCHAR, @IsYeriNo)+'' nolu işyerinin kasa hareketleridir. [212]'';
                SELECT @Mesaj+='''';
                SET @vucut = ''<html>''+''<body>''+''<H3 style = "color:blue;"><i>''+@Mesaj+''</i> </H3>''+''<H2 style="text-align:center; color:orange;"> Kasa Hareketleri </H2>''+''<H4> ''+''<ul style = "list-style-type:disc">''+''<p>''+''<li>''+@KasaBakiye+''</li>''+''</ul>''+''</p>''+''<H4> ''+''
                    <table border = 1> 
                    <tr>
                    <th> Tarih </th> <th> Fiş No </th> <th> İşlem Türü </th> <th> Cari Başlığı </th> <th> Açıklama </th> <th> Tutar </th> <th> Kur </th> <th> Döviz Tutar </th> <th> Özel Kodu </th> <th> Yetki Kodu </th> <th> İş Yeri </th> <th> Kaydeden Kullanıcı </th>
                    </tr>'';
                SET @vucut = @vucut+@xml+''</table></body></html>''+''[''+CONVERT(NVARCHAR, @IsYeriNo)+'' nolu işyerinin ''+
                (
                    SELECT KasaKodu
                    FROM @mad
                    WHERE logicalref = @s
                )+'' kodlu kasanın ''+CONVERT(NVARCHAR, @KacGunOnce)+'' gün öncesine ait hareketleridir.] Bu maile cevap vererek bilgilendirme maili ile alakalı tavsiyenizi yazabilirsiniz.'';
            END; --Mail verilerini hazırla



            BEGIN
                SET @AliciAdresler =
                (
                    SELECT m.[AlıcıAdresler]
                    FROM @mad m
                    WHERE m.logicalref = @s
                );
                SET @BilgiAliciAdresler =
                (
                    SELECT m.[BilgiAlıcıAdresler]
                    FROM @mad m
                    WHERE m.logicalref = @s
                );
                SET @GizliBilgiAliciAdresler =
                (
                    SELECT m.[GizliBilgiAlıcıAdresler]
                    FROM @mad m
                    WHERE m.logicalref = @s
                );
            END; -- Mail adreslerini değişkenlere tanımla



            BEGIN
                EXEC msdb.dbo.sp_send_dbmail
                     @body = @vucut,
                     @body_format = ''HTML'',
                     @subject = @Baslik,
                     @importance = ''HIGH'',
                     @reply_to = ''mustafaalperen@fimar.com.tr'',
                     @profile_name = ''MAD_Mail'',
                     --@recipients = @AliciAdresler,
                     --@copy_recipients = @BilgiAliciAdresler,
                     @blind_copy_recipients = @GizliBilgiAliciAdresler,
                     @execute_query_database = ''FIMAR_MHB'';
            END; --Mail Gönder



            BEGIN
                DECLARE @GonderilenMailBilgisi NVARCHAR(MAX)= ''Mail (Id: ''+CONVERT(NVARCHAR, @@IDENTITY)+'') queued.'';
                EXEC sp_MAD_Loglar_Ins
                     @FORM = ''AGENT_MAD_08_00_Mailleri'',
                     @KULLANICI = ''Sql Agent'',
                     @TERMINAL = ''427'',
                     @ASISTAN = @GonderilenMailBilgisi,
                     @DERECE = ''Bal'';
            END; --Loglama yap



            BEGIN
                SET @s = @s + 1;
            END; --Döngü için döngü değişkenini +1 arttır               

            /**** DÖNGÜ BİTİŞ ****/

        END;
END; -- Mail gönderme döngüsü
';
EXECUTE sp_executesql @SqlQuery;  

【问题讨论】:

EXECUTE bolck 之前,您可以放置​​PRINT @SqlQuery 并发布实际查询。它可以帮助我们确定实际问题 为你使用的 DBMS 添加标签 您使用的数据库设计非常糟糕 - LG_'+@SirketNo+'_01 【参考方案1】:

考虑更改您的数据库设计并尽量减少动态 SQL 的使用。现在您的动态 SQL 代码总是容易出现神秘错误和 SQL 注入攻击

正如@PPP 所建议的,您必须获取生成的代码并查看其中的问题 - 在 SQL Server Management Studio 中对其进行调试。

要做到这一点,你必须使用这个命令:

PRINT CAST(@SqlQuery as ntext)

因为您动态生成的 sql 超过 8000 个字符。见this question。

然后将其复制到新窗口并查看语法错误并修复它们,然后修复适当生成它的代码。

【讨论】:

以上是关于关键字“FOR”XML 附近的语法不正确的主要内容,如果未能解决你的问题,请参考以下文章

关键字“read”附近的语法不正确

关键字“或”附近的语法不正确

在关键字“pivot”附近出现语法错误,提示语法不正确。我在这里想念啥

SQL错误关键字'user'附近的语法不正确[重复]

关键字 UNION 附近的语法不正确

关键字“JOIN”附近的语法不正确。使用 asp.net [重复]