Avatar billede thomas_regin Nybegynder
31. oktober 2002 - 20:51 Der er 25 kommentarer og
1 løsning

SQL server agent.

Hejsa!

Et spørgsmål til de lidt mere hardcore SQL-administratorer, tror jeg:

Hvordan afvikler jeg et job på samtlige databaser i systemet samtidigt!?

Mit problem er flg.:

I en web-applikation holder min SQL-server styr på hvilke sessions der er aktive på mine websites. Der kører et Job hvert 20. minut, der sikrer at alle sessions bliver "nulstillede", hvis der ikke har været aktivitet i 20 minutter. Problemet er bare, at hver gang jeg replikerer en database, så skal jeg rent fysisk gå ind og oprette et nyt job for hver database. Er der ikke mulighed for, at man kan sætte en option til at opdatere samtlige databaser hvert 20. minut med den samme stored procedure?

Håber, at spørgsmålet er forstået! ;)

Mvh,

Thomas Regin.
Avatar billede kennethrisum Nybegynder
03. november 2002 - 09:30 #1
Hvilket job kører du?

Hvis du kan køre det med T-SQL kan du køre en cursor med sql'en

select name from sysdatabases where sid<>0x01

i master databasen.

Her får du så samtlige databaser. Herefter kan du loope igennem dem og udføre jobbet på databasen.

Men fortæl lidt om hvad det er for et job du vil udføre ;-)
Avatar billede thomas_regin Nybegynder
03. november 2002 - 16:03 #2
Hejsa,

Det er netop et T-SQL job jeg kører. Indtil nu har jeg oprettet et job for hver database, som laver en "Exec sp_MystoredProcedure" på pågældende database.

Så hvad du siger er, at jeg istedet kan lave en Select på sysdatabases i Master-tabellen, og så loope igennem?

Der er en lille bi-ting forbundet ved mit spørgsmål, for det er nemlig ikke *ALLE* databaserne der indeholder den tabel, som jeg skal checke på. Findes der også en mulighed for at checke, om den pågældende tabel eksisterer før man afvikler sin stored procedure? Den skal f.eks ikke køres på "Northwind" eller "Pubs"..

På forhånd tak for hjælpen,

Thomas Regin.
Avatar billede kennethrisum Nybegynder
03. november 2002 - 16:16 #3
Du kan bruge:

Select count(name) from sysobjects where type='U' and name = 'TABEL'

Hvis TABEL findes i databasen retuneres 1 ellers 0.
Avatar billede kennethrisum Nybegynder
03. november 2002 - 16:17 #4
PS. Den ovenstående query skal køres i den relevante database.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 16:38 #5
Hejsa igen,

Det lyder helt rigtigt det du er inde på, men jeg har lidt svært ved at formulere min kode. Du kan muligvis hjælpe mig her også.

Problemet er at fange de returnerede værdier. Her er min kode:

Select name from sysdatabases where sid <> 0x01
return name

while name <> null
select count(name) as newName from sysobjects where type='u' and name = "SESSIONS"
return newName

if newName <> null
  exec killSessions newName
loop

Jeg får flg. fejl:

"Error 178: A RETURN statement with a return value cannot be used in this context" og

"Incorrect syntax near loop"

Det er første gang jeg skal bruge loops i en Stored procedure, så bær venligst over med mig! ;)

Mvh,

Thomas Regin.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 16:43 #6
PS.: Når nu loopet fungerer efter hensigten, hvordan sikrer jeg så, at den stored procedure jeg forsøger at eksekvere benytter den rigtige database?

Når jeg bruger "exec sp_killSessions", så udspecificerer jeg jo ikke i hvilken database den skal opdatere!

Beklager, at jeg er besværlig! Hehe..

/thomas
Avatar billede kennethrisum Nybegynder
03. november 2002 - 18:07 #7
Først: Denne sql returnere samtlige databaser, der indeholder tabellen 'authors'


DECLARE DBCursor CURSOR
KEYSET
FOR Select name from sysdatabases where sid <> 0x01


DECLARE @name sysname
DECLARE @SQL nvarchar(400)
DECLARE @Count int
OPEN DBCursor

FETCH NEXT FROM DBCursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)
    BEGIN
        SELECT @Count=object_id(@name + '..authors')
        IF @Count>0
            Begin
                PRINT @Name
            End
    END
    FETCH NEXT FROM DBCursor INTO @name
END

CLOSE DBCursor
DEALLOCATE DBCursor
GO

Mht. "exec sp_killSessions" skal du bruge:

exec sp_executesql N'use ' + @name + ' exec sp_killsessions'

i stedetfor linien PRINT @name i det ovenstående.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 20:12 #8
Hejsa igen!

Det ser ud som om dette er løsningen, men den bliver ved med at melde fejl på:

exec sp_executesql N'use ' + @name + ' exec sp_killsessions'

Error 170: Incorrect syntax near '+'

Jeg har prøvet næsten alle kombination, og så meget kender jeg åbenbart ikke til SQL-kode, at jeg lige kan rette det.

Jeg forhøjer lige pointene lidt, så du også føler, at du får "betaling" for dit arbejde.

Mvh,

Thomas Regin
Avatar billede kennethrisum Nybegynder
03. november 2002 - 20:16 #9
Sorry, det skulle have været

exec sp_executesql N'use ' + @name + N' exec sp_killsessions'
Avatar billede thomas_regin Nybegynder
03. november 2002 - 20:25 #10
Jeg er ked af det, men det gi'r fuldstændigt samme fejl! :(

DECLARE DBCursor CURSOR
KEYSET
FOR Select name from sysdatabases where sid <> 0x01


DECLARE @name sysname
DECLARE @SQL nvarchar(400)
DECLARE @Count int
OPEN DBCursor

FETCH NEXT FROM DBCursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)
    BEGIN
        SELECT @Count=object_id(@name + '..sessions')
        IF @Count>0
            Begin
            exec sp_executesql N'use ' + @name + N' exec KillSessions'
            End
    END
    FETCH NEXT FROM DBCursor INTO @name
END

CLOSE DBCursor
DEALLOCATE DBCursor
GO

Mvh,

/thomas
Avatar billede kennethrisum Nybegynder
03. november 2002 - 20:33 #11
OK prøv med:

set @SQL=N'use ' + @name + N' exec KillSessions'
exec sp_executesql @SQL

i stedet for "exec sp_executesql N'use ' + @name + N' exec KillSessions'
"
Avatar billede thomas_regin Nybegynder
03. november 2002 - 20:44 #12
Herligt! Så langt så godt!

Nu melder den ikke fejl, men den afvikler heller ikke min KillSessions procedure. Er der nogle muligheder for at lave noget fejlsøgning, evt. udskrive nogle variabler eller noget, når man afvikler jobbet, så man kan se hvorfor den ikke fungerer?

/thomas
Avatar billede kennethrisum Nybegynder
03. november 2002 - 20:47 #13
Jeg plejer at bruge print kommandoen:

f.eks. "PRINT @SQL" for at se hvilke variable der har hvilke værdier.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 20:50 #14
Yes, det har jeg lige prøvet. Og her har jeg fundet ud af, at koden aldrig når ind i:

IF (@@fetch_status <> -2)

@@fetch_status bliver aldrig -2.

/thomas
Avatar billede thomas_regin Nybegynder
03. november 2002 - 20:53 #15
Hov.. Omvendt..

Fetch status er åbenbart altid -2 for den kommer aldrig ind i den IF-sætning!
Avatar billede thomas_regin Nybegynder
03. november 2002 - 20:54 #16
Og den når heller ikke ind i

WHILE (@@fetch_status <> -1)
Avatar billede kennethrisum Nybegynder
03. november 2002 - 20:57 #17
Prøv at ændre linierne:

DECLARE DBCursor CURSOR
KEYSET
FOR Select name from sysdatabases where sid <> 0x01

Til

DECLARE DBCursor CURSOR
KEYSET
FOR Select name from sysdatabases

Det er jo ligegyldigt nu hvor der checkes på, om en specifik tabel eksisterer.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 21:06 #18
Okay.. Nu looper den igennem og @@fetch_status er lig med 0 hele vejen igennem.. Men det virker stadig ikke helt. Men hvis jeg indsætter følgende linie:

print @name

i det følgende

IF (@@fetch_status <> -2)
    BEGIN
        SELECT @Count=object_id(@name + 'SESSIONS')
    IF @Count>0
    print @name /* Hvis jeg indsætter denne linie, så virker det */
            Begin
        set @SQL=N'use ' + @name + N' exec KillSessions'
        exec sp_executesql @SQL
            End
    END

ja, så virker det??

Men det holder jo ikke, når det skal op og ligge på web-serveren!

/thomas
Avatar billede kennethrisum Nybegynder
03. november 2002 - 21:18 #19
Det lyder mystisk!

Men hvis det ikke er en stavefejl at linien:

SELECT @Count=object_id(@name + 'SESSIONS')

ikke hedder

SELECT @Count=object_id(@name + '..SESSIONS')

Så er det fordi Begin/End blokken ligger udenfor IF sætningen når du indsætter din linie. Dette betyder, at der ikke laves check på om tabellen eksisterer i databasen.

IF sætningen 'dækker' kun PRINT @name kommandoen.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 21:24 #20
Haha.. Det er for sort der her! :/

Nu har jeg ændret det tilbage, så der står ...SESSIONS, og det giver samme resultat: Intet. Den siger bare

The command(s) completed successfully.

Uden, at der er ændret en tøddel.

Hvis jeg sætter print @name ind efter "BEGIN" så sker der ingenting. Hvis jeg derimod sætter det lige før "BEGIN", så virker det perfekt. Den looper igennen, ekekverer proceduren og adskillige rows bliver "affected" fuldstændigt som den skal!?

Jeg fatter minus! ;)

/thomas
Avatar billede kennethrisum Nybegynder
03. november 2002 - 21:36 #21
@name indeholder databasenavnet. SESSIONS er den tabel der skal checkes på.

For at tage fat i en tabel (fully qualified) bruger man:

<DB>.<OWNER>.<TABEL>

Man kan dog sagtens udelade <OWNER>. Så det der skal stå er:

SELECT @Count=object_id(@name + '..SESSIONS')

Prøv at lave en print på @Count

Prøv evt. også at køre:

SELECT object_id('pubs..authors')

For at se hvad den retunerer.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 21:43 #22
@count returnerer intet. Den er totalt tom, men funktionen looper igennen og executer KillSessions fuldstændigt som den skal. Fjerner jeg "print @count" virker det ikke længere!

SELECT object_id('pubs..authors') returner ingen ting, men looper igennen som den skal, så længe der står "print @count". Fjerner jeg dette, så looper den heller ikke og returnerer ingen ting!

Det er MEGET mystisk!

/thomas
Avatar billede kennethrisum Nybegynder
03. november 2002 - 21:56 #23
OK.

Så er det din object_id der fejler.

Hvis det virker udemærket uden checket med object_id, så kan du helt fjerne dette check.

Alternativt kan du prøve at se på hvilken account du er logget på med. Desuden kan du eksplicit skrive Owner navnet i object_id så detbliver til:

select @count = object_id(@name + '.dbo.sessions')

forudsat at det er dbo der er ejer af tabellerne i din database.
Avatar billede thomas_regin Nybegynder
03. november 2002 - 22:06 #24
Bingo!! Det var lige det der skulle til!

Jeg skrevt .dbo.SESSIONS, og så funkede det!! :)

Herligt, herligt!!

Undskyld, at du skulle gennemgå sådan et helvede! Fantastisk arbejde fra din side!

Jeg takker mange gange for din hjælp!!

Med taknemmelige hilsner,

Thomas Regin.
Avatar billede kennethrisum Nybegynder
03. november 2002 - 22:08 #25
Selv tak.

Det var jo ikke et helvede, men en øvelse i at finde alle de fejl muligheder der er, når man skal lave en 'løsning' over nettet ;-)
Avatar billede thomas_regin Nybegynder
03. november 2002 - 22:13 #26
Det er jo altid en udfordring! :)

Jeg tror jeg skal prøve lidt mere SQL-programmering. Det er sgu' lidt anderledes at arbejde i end de sædvanlige sprog jeg bruger, men det er vel bare en vanesag! Spændende er det ihvertfald! Der er mange muligheder!!

Ha' en fornøjelig aften og endnu engang tak for din store indsats! :)

/thomas
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester