🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.bazy-danych
Article #195608

Re: Dziwne zmienne w MS-SQL

#195608
From: Adam
Date: Sat, 16 Jun 2018 10:45
362 lines
14062 bytes
W dniu 2018-06-15 o 18:03, Stokrotka pisze:
> 
> 
>> Dlaczego zmienne w pewnych sytuacjach nie działają jak zmienne?
>>
>> Przykład _NIE_ działający:
>>
>> use master
>>
>> declare @TaBelKa nvarchar(40)
>> set @TaBelKa = 'sys.tables'
>> select * from @TaBelKa
>>
>> Zmienna niby jest "napompowana" wartością, gdyż select @TaBelKa  
>> zwraca wartość prawidłową.
>>
>>
>> Dlaczego trzeba tworzyć jakieś karkołomne konstrukcje typu:
>>
>> use master
>>
>> declare @TaBelKa nvarchar(40)
>> set @TaBelKa = 'sys.tables'
>> DECLARE @SQL NVARCHAR(100)
>> SET @SQL = N'SELECT * FROM ' + @TaBelKa
>> EXECUTE sp_executesql @SQL
>>
>>
>> Ki diabeł?
>> O co chodzi?
>>
> Wydaje mi się, że coś utrudniasz.

Może4sz wyjaśnić znaczenie "utrudniasz"?

> Według mnie pierwszy pszykład nie powinien iść,

Uzasadnienie?

Zakładam zmienną:
	declare @TaBelKa nvarchar(40)

Wypełniam wartością:
	set @TaBelKa = 'sys.tables'

Sprawdzam, czy wartość jest:
	select @TaBelKa

Zwraca prawidłową wartość.

Więc nieco inaczej, np:
	select 'wartość zmiennej: ' + @TaBelKa + ', a dzisiaj mamy ' + 
convert(nvarchar(MAX), GETDATE(), 20)

też wartości zwracane prawidłowo.

Dlaczego więc nie działa tu:
	select * from @TaBelKa

Znaczy: widzę, że zgłasza niezgodność zmiennej. Ale dlaczego?

Jeśli tabela ma kilka kolumn, to nie ma problemu - można deklarować. Ale 
jeśli tabel jest ok. 300, a w niektórych po kilkadziesiąt i więcej 
kolumn, to zaczyna się problem.


> a drugi to jakaś skomplikowana kopia
> z jakiegoś pszykładu, gdzie nie wszystko jest niezbędne.

O czym Ty piszesz? Jaka kopia? Z palca pisałem.
Możesz powiedzieć, co jest niepotrzebne? Chętnie się dowiem, bo o to mi 
chodzi.

Sprawdzałem na MS-SQL od 2005 do 2016. Starszych nie sprawdzałem, już 
raczej nie ma potrzeby.


Teraz - dlaczego pytam.

Otóż, konstruując większe zapytania i korzystając z konstrukcji
SET @SQL = N'
to w edytorze Management Studio wszystko po znaku ['] już nie jest 
kontrolowane względem składni.
Rodzi to możliwość popełnienia błędów choćby literowych, a znaleźć taki 
w większych zapytaniach to problem.

Poniżej przykład jednego z zapytań, niezbyt zresztą długiego:

=============================================

DECLARE @DATA12 datetime;
set @DATA12 = '20120101';


SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

--Wyliczanie poziomów grup produktów
WITH g(gid, gidTyp, kod, gidNumer, grONumer, poziom, sciezka)
AS
(
       SELECT TwG_TwGID, TwG_GIDTyp, TwG_Kod, TwG_GIDNumer, 
TwG_GrONumer, 0 as poziom, convert(nvarchar(1024), '') as sciezka
       FROM CDN.TwrGrupy
       WHERE TwG_TwGID = 0

       UNION ALL

       SELECT TwG_TwGID, TwG_GIDTyp, TwG_Kod, TwG_GIDNumer, 
TwG_GrONumer, p.poziom + 1 as poziom, convert(nvarchar(1024), p.sciezka 
+ N'\' + c.TwG_Kod) as sciezka
       FROM g p
       JOIN CDN.TwrGrupy c
       ON c.TwG_GrONumer = p.gidNumer
       WHERE c.TwG_TwGID <> 0 AND c.TwG_GIDTyp = -16
)

SELECT * INTO #tmpTwrGr FROM g

DECLARE @poziom int
DECLARE @poziom_max int
DECLARE @sql nvarchar(max)
SELECT @poziom_max = MAX(poziom) FROM #tmpTwrGr
SET @poziom = @poziom_max
SET @sql = N''

WHILE @poziom >= 0
BEGIN
	SET @sql = N'ALTER TABLE #tmpTwrGr ADD Poziom' + CAST(@poziom AS 
nvarchar) + N' nvarchar(40), ONr' + CAST(@poziom AS nvarchar) + N' 
nvarchar(40)'
     EXEC(@sql)

     IF @poziom = @poziom_max
		BEGIN
			SET @sql = N'UPDATE #tmpTwrGr
				SET ONr' + CAST(@poziom AS nvarchar) +  '= grONumer '
			EXEC(@sql)
			
			SET @sql = N'UPDATE #tmpTwrGr
				SET Poziom' + CAST(@poziom AS nvarchar) + ' = kod'
			EXEC(@sql)
		END
     ELSE
		BEGIN
     		SET @sql = N'UPDATE c
				SET c.Poziom' + CAST(@poziom AS nvarchar) + N' = (
					CASE WHEN c.poziom <=' + CAST(@poziom AS nvarchar) + N' THEN 
CAST(c.kod AS nvarchar)
					ELSE CAST(p.kod AS nvarchar) END)
				FROM #tmpTwrGr c
				LEFT JOIN #tmpTwrGr p
				ON c.ONr' + CAST(@poziom + 1 AS nvarchar) + '= p.gidNumer '
			EXEC(@sql)
	
			SET @sql = N'UPDATE c
				SET c.ONr' + CAST(@poziom AS nvarchar) + N' = (
					CASE WHEN c.poziom <=' + CAST(@poziom AS nvarchar) + N' THEN 
CAST(c.grONumer AS nvarchar)
					ELSE CAST(p.grONumer AS nvarchar) END)
				FROM #tmpTwrGr c
				LEFT JOIN #tmpTwrGr p
				ON c.ONr' + CAST(@poziom + 1 AS nvarchar) + '= p.gidNumer '
				EXEC(@sql)
		END
     SET @poziom = @poziom - 1
END

declare @select varchar(max)
declare @kolumny varchar(max)
declare @kolumny2 varchar(max)
declare @i int

set @kolumny = ''
set @kolumny2 = ''
set @i=0
while (@i<=@poziom_max)
begin
	set @kolumny = @kolumny + ',"Produkt Grupa Poziom ' + LTRIM(@i) + '" = 
CASE WHEN Poz.Poziom' +LTRIM(@i) + ' IS NULL THEN ''(NIEPRZYPISANE)'' 
ELSE Poz.Poziom' + LTRIM(@i) + ' END'
	set @kolumny2 = @kolumny2 + ',Poz.Poziom' +LTRIM(@i)
	set @i = @i + 1
end

--W³aœciwe zapytanie
set @select =
'SELECT
	DB_NAME() [Baza Firmowa],
	
	MAX(Twr_Kod) [Produkt Kod],
	25003 [Produkt Kod __PROCID__Towary__], Twr_twrId [Produkt Kod __ORGID__],	
	
	MAX(Twr_Nazwa) [Produkt Nazwa],
	25003 [Produkt Nazwa __PROCID__], Twr_twrId [Produkt Nazwa __ORGID__],
	
	MAX(CASE
		WHEN Twr_Typ = 0 AND Twr_Produkt = 0 THEN ''Us³uga Prosta''
		WHEN Twr_Typ = 1 AND Twr_Produkt = 0 THEN ''Towar Prosty''
		WHEN Twr_Typ = 0 AND Twr_Produkt = 1 THEN ''Us³uga Z³o¿ona''
		WHEN Twr_Typ = 1 AND Twr_Produkt = 1 THEN ''Towar Z³o¿ony''
		ELSE ''(NIEOKREŒLONY)''
	END) [Produkt Typ],
	ISNULL(MAX(Kat_KodOgolny),''(NIEOKREŚLONA)'')  [Produkt Kategoria 
Ogólna], ISNULL(MAX(Kat_KodSzczegol),''(NIEOKREŚLONA)'') [Produkt 
Kategoria Szczegółowa], MAX(Twr_JM) [Jednostka Miary],
	"Ilość Stan Początkowy H"=0, "Ilość Stan Początkowy M"=0,
	"Ilość FZ"=SUM(IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=301 THEN 
1 ELSE 0 END),
	"Ilość FS"=SUM(IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=302 THEN 
1 ELSE 0 END),
	"Ilość PA"=SUM(IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=305 THEN 
1 ELSE 0 END),
	"Ilość PZ"=SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=307 THEN 
1 ELSE 0 END),
	"Ilość PKA"=SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=313 
THEN 1 ELSE 0 END),
	"Ilość PW"=SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu IN 
(310,303,317) THEN 1 ELSE 0 END),
	"Ilość MM OL"= SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu = 
312 AND TrN_Rodzaj = 312010 THEN 1 ELSE 0 END),
	"Ilość WZ"=SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=306 THEN 
1 ELSE 0 END),
	"Ilość WKA"=SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu=314 
THEN 1 ELSE 0 END),
	"Ilość RW"=SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu IN 
(304,318) THEN 1 ELSE 0 END),
	"Ilość MM LO"= SUM( IsNull(TrE_Ilosc,0)*CASE WHEN TrE_TypDokumentu = 
312 AND TrN_Rodzaj = 312100 THEN 1 ELSE 0 END),
	"Wartość Stan Początkowy H"=0, "Wartość Stan Początkowy M"=0,
	"Wartość FZ"=SUM(IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=301 THEN 1 ELSE 0 END),
	"Wartość FS"=SUM(IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=302 THEN 1 ELSE 0 END),
	"Wartość PA"=SUM(IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=305 THEN 1 ELSE 0 END),
	"Wartość PZ"=SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=307 THEN 1 ELSE 0 END),
	"Wartość PKA"=SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=313 THEN 1 ELSE 0 END),
	"Wartość PW"=SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN TrE_TypDokumentu 
IN (310,303,317) THEN 1 ELSE 0 END),
	"Wartość MM OL"= SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu = 312 AND TrN_Rodzaj = 312010 THEN 1 ELSE 0 END),
	"Wartość WZ"=SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=306 THEN 1 ELSE 0 END),
	"Wartość WKA"=SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=314 THEN 1 ELSE 0 END),
	"Wartość RW"=SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN TrE_TypDokumentu 
IN (304,318) THEN 1 ELSE 0 END),
	"Wartość MM LO"= SUM( IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu = 312 AND TrN_Rodzaj = 312100 THEN 1 ELSE 0 END),
	"Ilość Stan Obecny"= (select sum(CDN.TwrZasoby.TwZ_Ilosc) from 
cdn.TwrZasoby where CDN.Towary.Twr_TwrId = CDN.TwrZasoby.TwZ_TwrId),
"Ilość 2012"=(select twi_ilosc from cdn.TwrIlosci
		where TwI_TwrId =CDN.Towary.Twr_TwrId and TwI_MagId = 1
		and twi_data=(select top 1 TwI_Data from cdn.TwrIlosci where TwI_TwrId 
= CDN.Towary.Twr_TwrId and TwI_MagId = 1 and  twi_data 
<=CONVERT(DATETIME,''' + CONVERT(VARCHAR,@DATA12,120) + ''',120) order 
by twi_Data desc)),


	"Ilość Stan Start"=(select twi_ilosc from cdn.TwrIlosci
		where TwI_TwrId =CDN.Towary.Twr_TwrId and TwI_MagId = 1
		and twi_data=(select top 1 TwI_Data from cdn.TwrIlosci where TwI_TwrId 
= CDN.Towary.Twr_TwrId and TwI_MagId = 1 and  twi_data 
<=CONVERT(DATETIME,''' + CONVERT(VARCHAR,@DATAOD,120) + ''',120) order 
by twi_Data desc)),
	"Ilość Stan Stop"=(select twi_ilosc from cdn.TwrIlosci
		where TwI_TwrId =CDN.Towary.Twr_TwrId and TwI_MagId = 1
		and twi_data=(select top 1 TwI_Data from cdn.TwrIlosci where TwI_TwrId 
= CDN.Towary.Twr_TwrId and TwI_MagId = 1 and  twi_data 
<=CONVERT(DATETIME,''' + CONVERT(VARCHAR,@DATADO,120) + ''',120) order 
by twi_Data desc))
' + @kolumny +
' FROM CDN.Towary
	LEFT OUTER JOIN cdn.TraElem ON TrE_TwrID=Twr_TwrID
	LEFT OUTER JOIN cdn.TraNag  ON TrN_TrNID=TrE_TrNID
	LEFT OUTER JOIN cdn.Magazyny ON Mag_MagID=TrN_MagZrdID
	LEFT OUTER JOIN cdn.Kategorie ON Kat_KatID=Twr_KatID
	LEFT JOIN #tmpTwrGr Poz ON Twr_TwGGIDNumer = Poz.gidNumer
WHERE (TrN_Bufor<>-1  AND TrN_Korekta IN (0,1) OR TrN_TrNID IS NULL)
	AND (((TrE_TypDokumentu IN (302,304,305,306,314,318) OR TrN_Rodzaj IN 
(312100)
	OR ((TrE_TypDokumentu IN (301,310,303,307,313,317) OR TrN_Rodzaj IN 
(312010)) AND TrN_Bufor=0))
	AND TrE_Aktywny<>0)	OR TrE_TrEID IS NULL)
	AND (TrN_DataOpe BETWEEN CONVERT(DATETIME,''' + 
CONVERT(VARCHAR,@DATAOD,120) + ''',120) AND CONVERT(DATETIME,''' + 
CONVERT(VARCHAR,@DATADO,120) + ''',120) OR TrE_TrEID IS NULL)
GROUP BY Twr_TwrID ' + @kolumny2 + '

UNION ALL

SELECT
	DB_NAME() [Baza Firmowa],
	
	MAX(Twr_Kod) [Produkt Kod],
	25003 [Produkt Kod __PROCID__Towary__], Twr_twrId [Produkt Kod __ORGID__],	
	
	MAX(Twr_Nazwa) [Produkt Nazwa],
	25003 [Produkt Nazwa __PROCID__], Twr_twrId [Produkt Nazwa __ORGID__],	

	MAX(CASE
		WHEN Twr_Typ = 0 AND Twr_Produkt = 0 THEN ''Us³uga Prosta''
		WHEN Twr_Typ = 1 AND Twr_Produkt = 0 THEN ''Towar Prosty''
		WHEN Twr_Typ = 0 AND Twr_Produkt = 1 THEN ''Us³uga Z³o¿ona''
		WHEN Twr_Typ = 1 AND Twr_Produkt = 1 THEN ''Towar Z³o¿ony''
		ELSE ''(NIEOKREŒLONY)''
	END) [Produkt Typ],
	ISNULL(MAX(Kat_KodOgolny),''(NIEOKREŚLONA)'') [Produkt Kategoria 
Ogólna], ISNULL(MAX(Kat_KodSzczegol),''(NIEOKREŚLONA)'')  [Produkt 
Kategoria Szczegółowa], MAX(Twr_JM) [Jednostka Miary],
	"Ilość Stan Początkowy H"=SUM(IsNull(TrE_Ilosc,0)*CASE WHEN 
TrE_TypDokumentu=301 THEN 1 WHEN TrE_TypDokumentu IN (302,305) THEN -1 
ELSE 0 END),
	"Ilość Stan Początkowy M"=SUM(IsNull(TrE_Ilosc,0)*CASE WHEN 
TrE_TypDokumentu IN (310,303,307,313,317) THEN 1 WHEN TrE_TypDokumentu 
IN (301,302,305) THEN 0 ELSE -1 END),
	"Ilość FZ"=0, "Ilość FS"=0,	"Ilość PA"=0, "Ilość PZ"=0,	"Ilość PKA"=0, 
"Ilość PW"=0, "Ilość MM OL"=0, "Ilość WZ"=0,	"Ilość WKA"=0, "Ilość 
RW"=0, "Ilość MM LO"=0,
	"Wartość Stan Początkowy H"=SUM(IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu=301 THEN 1 WHEN TrE_TypDokumentu IN (302,305) THEN -1 
ELSE 0 END),
	"Wartość Stan Początkowy M"=SUM(IsNull(TrE_WartoscNetto,0)*CASE WHEN 
TrE_TypDokumentu IN (310,303,307,313,317) THEN 1 WHEN TrE_TypDokumentu 
IN (301,302,305) THEN 0 ELSE -1 END),
	"Wartość FZ"=0, "Wartość FS"=0,	"Wartość PA"=0, "Wartość PZ"=0, 
"Wartość PKA"=0, "Wartość PW"=0, "Wartość MM OL"=0,	"Wartość WZ"=0, 
"Wartość WKA"=0, "Wartość RW"=0, "Wartość MM LO"=0,
	"Ilość Stan Obecny"=0,
	"Ilość 2012"=0,
	"Ilość Stan Start"=0,
	"Ilość Stan Stop"=0
' + @kolumny +
' FROM CDN.Towary
	LEFT OUTER JOIN cdn.TraElem ON TrE_TwrID=Twr_TwrID
	LEFT OUTER JOIN cdn.TraNag  ON TrN_TrNID=TrE_TrNID
	LEFT OUTER JOIN cdn.Magazyny ON Mag_MagID=TrN_MagZrdID
	LEFT OUTER JOIN cdn.Kategorie ON Kat_KatID=Twr_KatID
	LEFT JOIN #tmpTwrGr Poz ON Twr_TwGGIDNumer = Poz.gidNumer
WHERE (TrN_Bufor<>-1  AND TrN_Korekta IN (0,1) OR TrN_TrNID IS NULL)
	AND (((TrE_TypDokumentu IN (302,304,305,306,314,318) OR TrN_Rodzaj IN 
(312100)
	OR ((TrE_TypDokumentu IN (301,310,303,307,313,317) OR TrN_Rodzaj IN 
(312010)) AND TrN_Bufor=0))
	AND TrE_Aktywny<>0)	OR TrE_TrEID IS NULL)
	AND (TrN_DataOpe < CONVERT(DATETIME,''' + CONVERT(VARCHAR,@DATAOD, 120) 
+ ''',120) OR TrE_TrEID IS NULL)
GROUP BY Twr_TwrID' + @kolumny2

exec (@select)

DROP TABLE #tmpTwrGr

=============================================


-- 
Pozdrawiam.

Adam
Technical Details
Message-ID: <pg2pop$u93$1$Adam@news.chmurka.net>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!news.chmurka.net!.POSTED.ent22.internetdsl.tpnet.pl!not-for-mail
References: <pg0f08$vgn$1$Adam@news.chmurka.net> <5b23e33e$0$589$65785112@news.neostrada.pl>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!news.chmurka.net!.POSTED.ent22.internetdsl.tpnet.pl!not-for-mail
From: Adam <a.g@poczta.onet.pl>
Newsgroups: pl.comp.bazy-danych
Subject: Re: Dziwne zmienne w MS-SQL
Date: Sat, 16 Jun 2018 12:45:46 +0200
Organization: news.chmurka.net
Message-ID: <pg2pop$u93$1$Adam@news.chmurka.net>
References: <pg0f08$vgn$1$Adam@news.chmurka.net> <5b23e33e$0$589$65785112@news.neostrada.pl>
NNTP-Posting-Host: ent22.internetdsl.tpnet.pl
Mime-Version: 1.0
Injection-Date: Sat, 16 Jun 2018 10:45:45 +0000 (UTC)
Injection-Info: news.chmurka.net; posting-account="Adam"; posting-host="ent22.internetdsl.tpnet.pl:83.15.205.22"; logging-data="31011"; mail-complaints-to="abuse-news.(at).chmurka.net"
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0
In-Reply-To: <5b23e33e$0$589$65785112@news.neostrada.pl>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit