关键字“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 附近的语法不正确的主要内容,如果未能解决你的问题,请参考以下文章