31. januar 2004 - 22:55Der er
14 kommentarer og 2 løsninger
Kalde StoredProcedure eller View med WHERE-betingelse
Hi E,
Jeg har lavet en StoredProcedure (SP) og et view med samme SQL streng (en lang satan med en masse joins fra forskellige tabeller).
Fra min ASP-side kalder jeg mit view med fx SELECT * FROM myView WHERE PK=2. Det går også fint nok, men spm er, om det er mere hensigtsmæssigt at kalde en SP ift. et view? I fald anbefalingen går på SP, hvad er så fordelen(e), og hvordan fletter jeg en WHERE-begtingelse ind i mit SP-kald på min ASP-side?
> Hvis du skal bruge en SP skal data til WHERE vel over som argument til SP. Jeps. Og det er jeg usikker på, hvordan jeg gør (i modtsætningen til i et view, hvor det jo er lige ud ad landevejen).
Normalt kalder jeg mine SP således:
Dim objCmd, objRS Set objCmd = Server.CreateObject("ADODB.Command") Set objCmd.ActiveConnection = objConn objCmd.CommandText = "myStoredProcedure" objCmd.CommandType = adCmdStoredProc Set objRS = Server.CreateObject("ADODB.Recordset") Set objRS = objCmd.Execute
Så jeg er ikke helt klar over hvordan jeg videregiver argumentet om, at det ikke er alle records i mit SP der skal output'es, men kun det hvor PK fx er 2.
Hm, umiddelbart kan jeg ikke lige få flette min betingelse ind med den model. Jeg kan udfra eksemplet se, at man kan tilføje ekstra parametre (data) til sin SP, men i dette tilfælde handler det jo om at sætte en betingelse for hvilket recordset jeg vil have fat i. Det er muligt, jeg blot ikke kan se nogen sammenhængen, men kan du i så fald ikke give et hurtigt eksempel på, hvordan jeg får flettet den betingelse ind i min SP inden den forlader serveren.
Som arne_v skriver, gemmes der en execution plan for en SP, hvilket speeder den noget op. Du skal dog være opmærksom på at hvis outputtet fra din SP er meget forskellige fra gang til gang, f.eks. en række nogle gange og tusindvis af række andre gange, kan det være en ulempe at bruge en SP, fordi de eksisterende execution plans ikke er korrekt for kaldet. Du kan oprette din SP med med WITH RECOMPILE, som gør at der laves en ny execution plan hver gang SP kaldes. Det er dog ikke det mest optimale.
Det ville være endnu bedre at bruge et INDEXED VIEW. Ticket er at lave et custered index på en kolonne i dit view. Det gør at viewets output gemmes fysisk på disk og er dermed meget hurtigt at tilgå. Vær opmærksom på at der er nogle ting, som skal være opfyldt for at du kan lave et indexed view: - VIEW skal oprettes med WITH SCHEMABINDING, som gør at de underliggende tabellers schema ikke kan ændres uden at viewet også opdateres. - Du kan ikke bruge nondeterministic functions i dit view, en nondeterministisk function er f.eks. GETDATE()
Du må ikke bruge: - ORDER BY - kan man heller ikke normalt i almindelige views, medmindre med bruger TOP 100% - COMPUTE, COMPUTE BY - TOP - Text, Ntext eller Image felter - DISTINCT - MIN, MAX, COUNT, STDEV, VARIANCE, AVG - Nested queries i FROM klausulen - Andre VIEWs i viewet - ROWSET function - UNION - Subqueries, OUTER JOIN og self JOIN.
Jeg har et par text felter og også en enkelt INNER JOIN (den er dog ikke med på mufoxes liste.. en smutter?), så jeg går ikke ud fra, at et indexed view er en option. Til gengæld hentes der kun én række (rekord) pr. databasekald, så en SP som arne_v beskriver er måske den hurtigste metode...?
Hm, kig lige på det her og fortæl mig hvor jeg er blind og døv. Jeg får ingen fejl, men absolut heller ingen data ud ad min ellers så medgørlige SQL Server:
SP SQL:
CREATE PROCEDURE IFI_ifi_admin.procGetPage2 @val INTEGER AS SELECT dbo.tblCMS.*, dbo.tblMenu.MenuCode AS MenuCode FROM dbo.tblCMS INNER JOIN dbo.tblMenu ON dbo.tblCMS.fkMenuUI = dbo.tblMenu.MenuUI WHERE dbo.tblCMS.fkMenuUI=@val GO
ASP script:
Dim objCmd, objRS, intPageUI, prmPageUI intPageUI = Request.QueryString("page") Set objCmd = Server.CreateObject("ADODB.Command") Set objCmd.ActiveConnection = objConn objCmd.CommandText = "procGetPage2" objCmd.CommandType = adCmdStoredProc Set prmPageUI = objCmd.CreateParameter("@val", adInteger, adParamInput) objCmd.Parameters.Append prmPageUI prmPageUI.Value = intPageUI Set objRS = Server.CreateObject("ADODB.Recordset") Set objRS = objCmd.Execute
Nå, det virker nu! Er @val et reserveret udtryk? Jeg ændrede dette og så virkede det...?
Jeg takker begge to. arne_v's løsning viste sig at være vejen frem i dette tilfælde, men mufoxes kommentar var relevant og gjorde mig lidt klogere, så det drypper lidt på ham også.
Det må det jo så være (selvom jeg ikke lige kan se hvad de skulle betyde).
Synes godt om
Ny brugerNybegynder
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.