13. marts 2007 - 15:25Der er
21 kommentarer og 1 løsning
Brug af et udtræk ny select?
Jeg har søgt her på eksperten men ikke lige fundet en løsning (muligvis har jeg ikke ledt grundigt nok), men her mit spørgsmål.
Jeg har behov for at bruge resultatkolonnen fra et udtræk som del af navnet på en anden tabel ... mere konkret her jeg pt. skrevet to SQL sætninger der hver for sig virker fint:
SQL sætning 1 (udtrækker en liste over navnene på mine databaser):
select name from master.dbo.sysdatabases
SQL sætning 2 (udtrækker en værdi fra én af mine databaser som hedder user_tkv_labj_db):
select max(hs_change_date) as senest_rørt from user_tkv_labj_db.td.history
Udfordringen er så at jeg gerne vil lægge disse SQL sætning 1 og 2 sammen, således at der i SQL sætning 2 bruges værdierne af navn fra SQL sætning 1 istedet for user_tkv_labj_db. Nogen der kan hjælpe mig med en SQL sætning der kan give mig et sådant udtræk?
Måske noget i denne stil: select name, max(hs_change_date) from master.dbo.sysdatabases t1 JOIN user_tkv_labj_db.td.history t2 ON t2.name= t1.name GROUP BY name Kommer lige an på navne i user_tkv_labj_db.td.history
Tak for dit svar, men jeg har ikke forklaret det godt nok.
Det er sådan at navnet user_tkv_labj_db ikke indeholder nogen name kolonne .. Faktisk skal user_tkv_labj_db slet ikke bruges men istedet alle navnene fra første udtræk en efter en istedet for der hvor der står user_tkv_labj_db.
Jeg kunne forestille mig noget i stil med en variabel der indeholder name fra første sql og så løber igennem og propper dette @n på den anden SQL .. måske som:
select max(hs_change_date) as senest_rørt from @n.td.history
Er jeg på rette spor .. eller kan det laves rent i SQL? Og kan jeg få resultatet ud i en stor resultattabel? (i dette tilfælde kan jeg sidde jeg på selve serveren og bruge SQL Server Enterprise manager istedet for applikationens egen SQL fortolker)
Måske noget i denne stil ? CREATE TABLE #temp ( table varchar(255), hs_change_Date datetime )
declare @minname varchar(255), @maxname varchar(255),@sql varchar(8000) select @minname=min(name), @maxname= max(name) from master.dbo.sysdatabases WHILE @minname<=@maxname BEGIN
SET @sql = 'SELECT '+@minname+',max(hs_change_date) FROM '+@minname INSERT INTO #temp EXEC( @sql)
select @minname=min(name) from master.dbo.sysdatabases WHERE name>@minname END
Af en eller anden grund kan jeg ikke få lov til at logge på vores server her til aften så jeg kan ikke lige prøve det af, men vil gøre det så hurtigt som muligt. En ting der undrer mig er sætningen:
SET @sql = 'SELECT '+@minname+',max(hs_change_date) FROM '+@minname
Så vidt jeg kan se ud fra din kode vil den lave sætninger i stil med: SELECT user_tkv_labj_db, max(hs_change_date) FROM user_tkv_labj_db
Det forstår jeg ikke helt? Jeg forestillede mig noget med en tabel der listede databasenavne og datoer i en liste i stil med:
Ok .. jeg vil prøve dette asap og vende tilbage. Tak for hjælpen indtil videre, det er bare skønt! (det er lige før jeg drømmer om SQL om natten nu :-)
WHILE @minname<=@maxname BEGIN SET @sql = 'SELECT '+@minname+',max(hs_change_date) FROM '+@minname+'.td.history' INSERT INTO #temp EXEC( @sql) EXEC( @sql) select @minname=min(name) from master.dbo.sysdatabases WHERE name>@minname END
SELECT * FROM #temp drop table #temp
Og jeg får en række fejlmeddelser tilbage:
Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'master.td.history'. Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'master.td.history'. Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'model.td.history'. Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'model.td.history'. Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'msdb.td.history'. Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'msdb.td.history'.
Og det er jo selvfølgelig fordi jeg ikke tænkte på at det kun er nogle af databaserne der her en history tabel (det har alle standerd SQL server tabellerne ikke). Spekulerer nu på hvordan jeg kan angive det .. men måske noget med at tilføje WHERE name LIKE 'user_' (eller sådan noget lignende for at angive at basenavnene starter på noget bestemt).
Men jeg får også en række andre fejl: Invalid column name 'user_best_practice'. Server: Msg 207, Level 16, State 3, Line 1 Invalid column name 'user_best_practice'. Server: Msg 207, Level 16, State 3, Line 1 .. osv.
Det kan jeg ikke lige gennemskue hvad skyldes .. kan det være pga. den der SELECT der bruger @minname?
I går fik jeg så endelig bakset lidt med dette igen. Hvis jeg udelader første felt i den temporære tabel så virker det faktisk !!! dvs. noget i stil med følgende prøvede jeg på serveren:
CREATE TABLE #temp (hs_change_Date datetime)
declare @minname varchar(255), @maxname varchar(255), @sql varchar(8000) select @minname=min(name), @maxname=max(name) from master.dbo.sysdatabases where name like 'prod_%'
WHILE @minname<=@maxname BEGIN SET @sql = 'SELECT max(hs_change_date) FROM '+@minname+'.td.history' INSERT INTO #temp EXEC( @sql) EXEC( @sql) select @minname=min(name) from master.dbo.sysdatabases WHERE name>@minname and name like 'prod_%' END
SELECT * FROM #temp drop table #temp
Og det er jo udmærket at få listen over datoer på den måde. Men jeg kan stadig ikke greje hvordan man i SQL angiver at man vil se en kontret værdi som resultat i en kolonne (i dette eksempel værdien af @minname) .. dvs. angive en sådan konkret værdi istedet for et kolonnenavn.
Hej dr_chaos .. jeg ville blot sige at ovenstående virker perfekt (dvs. hvor jeg har fjernet table_name varchar(255) fra CREATE TABLE linien og tilsværende kun undtrækker
SET @sql = 'SELECT max(hs_change_date) FROM ..
istedet for
SET @sql = 'SELECT '+@minname+',max(hs_change_date) FROM ..
Det der så vidt jeg kan se er problemet er at @minname indeholder en konkret værdi dvs. navnet på en database og ikke som et kolonnenavn som SELECT vil forvente. Det jeg så spørger om er hvordan (eller om man i det hele taget kan) få værdien af @minname ind i første kolonne af den temporære tabel, når det jo ikke reelt set er et udtræk men blot en angivelse af en værdi.
Som workaround laver jeg pt. to SQL. Den første som giver mig listen over navne: select name from master.dbo.sysdatabases where name like 'prod_% (dette copy paster jeg så over i et excel regneark)
Dernæst laver jeg ovenstående løkke byggende på dit forslag men kun med datoer. (dette copy paster jeg så over i en anden kolonne i regnearket)
På den måde får jeg et regneark med to kolonner. Men ville være frækt (og mere flexibelt) hvis det kunne klares fra SQL direkte at få de to kolonner dannet.
Ved du hvad dr_chaos .. DET VIRKER med de extra 'plinger', troede ellers jeg havde prøvet det hele. Tusind tak for din hjælp og udholdenhed! Tak også for tippet med print.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.