2017-02-10 4 views
2

Ich habe ein paar gespeicherte Prozeduren, die dynamisches SQL verwenden. Ich möchte sie wirklich ändern, so dass sie nicht dynamisch sind, nur weil sie wegen der Fehlerbehandlung sehr lästig sein können, Fehler zu beheben und zu ändern (das Klicken auf die Fehlermeldung führt Sie nicht zu dem Fehler). Ich weiß, dass ich den Text auswählen und es als reguläres SQL einfügen kann, um dabei zu helfen, aber es ist ziemlich frustrierend.Alternative zu dynamischem SQL

Das Problem dabei ist, dass die Abfragen viel langsamer ablaufen, wenn sie nicht dynamisch sind. Insbesondere ist die where-Klausel aufgrund ihrer erhöhten Flexibilität in der dynamischen Abfrage viel schneller. Zum Beispiel würde die statische where-Klausel wie etwas sein:

where 
    SomeColumn = case when @variable1 = 0 then SomeColumn else @variable1 end 
and(
    (@variable2 = -2 and SomeColumn2 = 1) 
    or (@variable2 = -1) 
    or (@variable2 = 0 and SomeColumn2 = 0 and SomeColumn3 = 0) 
    or (@variable2 = 1 and SomeColumn2 = 0 and SomeColumn3 > 0) 
    ) 

Aber die dynamische where-Klausel wäre:

where ' + @SomeCondition + @SomeCondition2 + ' 

eine Case-Anweisung wie folgt aus:

declare @SomeCondition nvarchar(max) = case 
    when @variable3 = -2 then N'Condition 1' 
    when @variable3 = 0 then N'Condition 2' 
    when @variable3 = 1 then N'Condition 3' 
    else N'' 
    end 

die einzige Lösung, die ich mir vorstellen kann, ist mit mehreren if Anweisungen und nur die WHERE-Klausel in jeder Anweisung ändern, aber das scheint unglaublich verschwenderisch und zeitaufwendig.

Gibt es noch andere Alternativen zu dynamischem SQL? Fehlt das, kann ich etwas tun, um den SQL-Server dazu zu bringen, mich richtig auf den Fehler zu verweisen?

+0

Verwenden Sie 'try' /' catch', um die durch das dynamische SQL verursachten Fehler zu erhalten? Vielleicht hilft das Beheben der Fehlerbehandlung, was Sie brauchen. Sogar mehrere 'if's können problematisch sein, wenn Sie nicht die Option' rekompilieren' verwenden. –

+0

Das wäre sehr hilfreich, die frustrierende Fehlerbehandlung ist eigentlich der einzige Grund, warum ich die dynamischen Abfragen ändern möchte. Würde ich einfach try/catch innerhalb der Variablen verwenden, die das SQL enthält, oder muss es außerhalb davon geschrieben werden? Ich bin mir nicht ganz sicher, wie ich mit dynamischem SQL vorgehen soll. –

+1

Sie könnten spezialisierte, optimierte Prozeduren erstellen und dann die richtige auf Basis Ihrer Parameter aufrufen, um die OR-Bedingungen zu vermeiden. Aber dann müssen Sie mehr Prozeduren verwalten. Meiner Erfahrung nach werden Sie nie eine "one-size-fits-all" -Abfrage (or-or-or-or-Muster im where) sowie dynamische oder spezialisierte Abfragen erhalten. –

Antwort

3

Fügen Sie die OPTION (RECOMPILE) der Abfrage hinzu. Dies führt dazu, dass es bei jeder Ausführung neu kompiliert wird, und der Optimierer ist intelligent genug, um die Prädikate zu verkürzen und zu eliminieren, ähnlich wie Sie es jetzt mit dynamischem SQL tun.

+0

Das hat meine Abfrage viel schneller gemacht (Danke!), Aber wenn ich auf die Fehlermeldung klicke, bringt mich das immer noch an eine zufällige Stelle in der Abfrage. Ich füge 'option (rekompilieren)' am Ende der Abfrage innerhalb der SQL-Variablen, die ausgeführt wird. –

+0

Bei komplexen Abfragen konnte die Zeilennummer, an der der Fehler aufgetreten ist, täuschen. Sie könnten auch auf dieses bekannte Problem stoßen: https://connect.microsoft.com/SQLServer/feedback/details/857794/. Wie auch immer, froh, dass das zumindest bei der Performance geholfen hat. – dean

+0

Meine Abfrage ist wie folgt strukturiert: '@SQLText deklarieren nvarchar (max) = N'BigQueryGoesHere Option (neu kompilieren) 'exec sys.sp_executesql @ SQLText' Sollte dies den Fehler korrekt zurückgeben? Ich werde an den richtigen Ort geleitet, wenn ich den Abfragetext auswähle und ihn als Standard-SQL einfüge. –

1

Alternativ können Sie ISNULL(NULLIF Syntax wie folgt verwenden. Aber verwenden Sie es mit Vorsicht, da es die Leistung negativ beeinflussen könnte.

where 
    SomeColumn = ISNULL(NULLIF(@variable1,''),SomeColumn) and 
    SomeColumn2 = ISNULL(NULLIF(@variable2,''),SomeColumn2) and 
    and so on.. 
+0

Ich habe das versucht, aber leider verlangsamt es die Abfrage erheblich. –

Verwandte Themen