/ Forside/ Teknologi / Udvikling / SQL / Spørgsmål
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
Where @RunAt = 1 i SP ???
Fra : stk
Vist : 648 gange
50 point
Dato : 09-07-01 11:49

Jeg vil gerne vælge nogle poster i en tabel (MS-SQL70):

TaskJobs:
Command RunAtAdd RunAtDelete
Cmd1 1 0
Cmd2 1 1

Jeg har prøvet følgende:
CREATE PROCEDURE GetJobs
   @RunAt varchar(20)
AS
   SELECT Command
   FROM TaskJobs
   WHERE @RunAt = 1

Men det vil den ikke helt være med til. Kan det lade sig gøre, eller _skal_ jeg bruge en case...when ting?

Stefan






 
 
Kommentar
Fra : damm


Dato : 09-07-01 11:59

Hej Stefan,

Det er lidt uklart, hvad du egentlig vil.

Den select du stiller op, vil returnere alt eller intet. Er det meningen?

Hvad mener du med "det vil den ikke helt være med til"? Får du en oversættelsesfejl? Hvilken? Eller giver den bare et andet resultat end det ønskede?

Vh
Kristian

Kommentar
Fra : stk


Dato : 09-07-01 12:24

Jeg vil angive hvilken kolonne, der skal være 1.
F.eks skal @RunAt = "RunAtAdd" returnere både Cmd1 og Cmd2, mens @RunAt = "RunAtDelete" kun skal returnere Cmd2.
Fejlen jeg får: Syntax error converting the varchar value 'RunAtAdd' to a column of data type int.

stefan

Kommentar
Fra : damm


Dato : 09-07-01 13:04

Det er stadig uklart, hvad du egentlig vil.

Det Kan ikke lade sig gøre at angive, at en hel kolonne skal være 1. Where-klausulen arbejder på reocrd (række, post) niveau, og du kan her angive krav til enkelte felter i en given record.

I din oprindelige select angiver du en sammenligning med en procedure-parameter og en konstant, begge dele ting, der intet har med den enkelte record at gøre. Resulatet af denne sammenligning vil enten være sand eller falsk, men have samme værdi for alle records. Med andre vil du enten få alle poster, eller ingen poster ud af dit procedure-kald. Mere præcist:

exec getJobs 1

vil returnere hele indholdet af taskJobs

exec getjobs 0 -- eller hvad som helst andet, der er forskellig fra 1

vil ikke returnere noget som helst.

Mht til den konkrete fejl: Når der er koks i typerne, så kig på type-erklæringerne. @RunAt er erklæret som varchar, altså en tekststreng. En sådan kan ikke umiddelbart sammenlignes med et tal (1).

Mulige rettelser:

1) Lav om på erklæringen af @RunAt til at være "@RunAT integer". Dette har konsekvenser for den kaldende miljø, hvorfor det muligvis ikke er ønskeligt.

2) Lav om på anvendelsen af @RunAt til: "where @RunAt = '1' "

Kommentar
Fra : damm


Dato : 09-07-01 13:10

Efter at have genlæst din kommentar forstår jeg nu endelig, hvad du vil. Svaret er: ja, det kan godt lade sig gøre:

CREATE PROCEDURE GetJobs
@RunAt varchar(20)
AS
declare @sql varchar(255)

select @sql = "SELECT Command FROM TaskJobs WHERE " + @RunAt + "= 1"

exec @sql



Kommentar
Fra : stk


Dato : 09-07-01 13:17

SELECT Command FROM TaskJobs
@RunAt = "RunAtAdd" => WHERE RunAtAdd = 1
@RunAt = "RunAtDelete" => WHERE RunAtDelete = 1

Det er altså værdien af @RunAt der skal bestemme, hvilken værdi, der skal undersøges i WHERE-sætningen.


Kommentar
Fra : stk


Dato : 09-07-01 13:20

Okay, det besvarer så også anden del af mit spørgsmål. En case...select er vel hurtigere end exec @sql?

Kommentar
Fra : damm


Dato : 09-07-01 13:25

Ja, jeg forstod endelig. Se min kommentar fra kl. 13:10.

Problemet består i at du blander data og programtekst sammen. Den slags kan ikke gøres implicit, det må nødvendvis gøres eksplicit. I min løsning sker det ved først at skabe en tekst-streng (data) og derefter (ved exec) at bede programmet om at opfatte det som programtekst.

Hvad du skrev oprindeligt var i virkeligheden

CREATE PROCEDURE GetJobs
@RunAt varchar(20)
AS
SELECT Command
FROM TaskJobs
WHERE "RunAtAdd" = 1



Kommentar
Fra : damm


Dato : 09-07-01 13:33

Om en case ... select er hurtigere end exec @sql ?

Det er svært at sige på forhånd. Den primære ulempe ved exec @sql er at du ikke får gemt din query-plan fra gang til gang og derfor har et mindre overhead idet den skal dannes. Hvor stort afhænger naturligvis af din maskine. Sidst jeg testede (på en alpha) lå det i størrelsesordenen 1-200 ms for simple sql-sætninger som denne.

Omvendt har jeg set eksempler på at mere komplekse strukturer medfører at optimizeren simpelthen ikke kan finde en god plan og går helt i skoven.

Eksempel:

CREATE PROCEDURE GetJobs
@RunAt varchar(20)
AS
SELECT Command
FROM TaskJobs
WHERE (@RunAt = "RunAtAdd" and runAtAdd = 1)
OR (@RunAt = "RunAtDelete" and runAtDelete = 1)

Denne konstruktion løser dit problem, men efterlader optimzeren ude af stand til at afgøre hvilket index, der skal benyttes. Resultatet vil være en tablescan. Ved små datmængder gør dette naturligvis ikke noget. Men ved bare 5-10000 rækker kan det være rigtig ubehageligt.





Kommentar
Fra : stk


Dato : 09-07-01 13:47

Se, det var jo lige det, jeg ledte efter.
Mange tak for din tålmodighed

stefan

Accepteret svar
Fra : damm

Modtaget 50 point
Dato : 09-07-01 13:57

For en god ordens kyld vil jeg lige score de point, der nu tilkommer mig...

CREATE PROCEDURE GetJobs
@RunAt varchar(20)
AS
SELECT Command
FROM TaskJobs
WHERE (@RunAt = "RunAtAdd" and runAtAdd = 1)
OR (@RunAt = "RunAtDelete" and runAtDelete = 1)

Denne konstruktion løser dit problem, men efterlader optimzeren ude af stand til at afgøre hvilket index, der skal benyttes. Resultatet vil være en tablescan. Ved små datmængder gør dette naturligvis ikke noget. Men ved bare 5-10000 rækker kan det være rigtig ubehageligt.

Kommentar
Fra : Nyhedsbruger


Dato : 18-07-01 07:46


"stk" <stk.news@kandu.dk> wrote in message
news:f5f27.1105$6x5.146210@news000.worldonline.dk...
> Jeg vil gerne vælge nogle poster i en tabel (MS-SQL70):
>
> TaskJobs:
> Command RunAtAdd RunAtDelete
> Cmd1 1 0
> Cmd2 1 1
>
> Jeg har prøvet følgende:
> CREATE PROCEDURE GetJobs
> @RunAt varchar(20)
> AS
> SELECT Command
> FROM TaskJobs
> WHERE @RunAt = 1
>
> Men det vil den ikke helt være med til. Kan det lade sig gøre, eller
> _skal_ jeg bruge en case...when ting?
>
Jeg antager at du vil lave en sp hvor du har en enkelt input parameter

CREATE PROCEDURE GetJobs (
@RunAt varchar(20)
)
AS
SELECT Command
FROM TaskJobs
WHERE RunAtAdd = @RunAt

Hvis du vil lave noget where clause på forskellige felter (RunAtAdd,
RunAtDelete) afhængig af @RunAt så er problemstillingen en anden

Skriv gerne igen hvis min antagelse er forkert

mvh/Peter Lykkegaard




Kommentar
Fra : stk


Dato : 18-07-01 11:13

Altså, jeg har en tabel, TaskJobs. Den indeholder nogle kommandoer i Command feltet. Disse kommandoer skal læses og sendes til et andet program alt after hvilken funktion dette andet program skal udføre, f.eks. AddUser og DelUser.

TaskJobs:
Command RunAtAdd RunAtDelete
Cmd1 1 0
Cmd2 1 1

Ved AddUser kalder programmet SP med @RunAt = RunAtAdd. Dette skulle så returnere Cmd1 og Cmd2 jf. ovenstående tabel.
Ved DelUser kalder programmet SP med @RunAt = RunAtDelete. Dette skulle så returnere Cmd1 jf. ovenstående tabel.

stefan

Du har følgende muligheder
Eftersom du ikke er logget ind i systemet, kan du ikke skrive et indlæg til dette spørgsmål.

Hvis du ikke allerede er registreret, kan du gratis blive medlem, ved at trykke på "Bliv medlem" ude i menuen.
Søg
Reklame
Statistik
Spørgsmål : 177417
Tips : 31962
Nyheder : 719565
Indlæg : 6407864
Brugere : 218876

Månedens bedste
Årets bedste
Sidste års bedste