none
Dynamischer String elegant bauen RRS feed

  • Frage

  • Hi,

    Gibt es eigentlich einen "schöneren" Weg ein dynamisches SQL zu bauen (für ein Pivot mit unbekannten Werten) so, dass ich Strings nicht quoten muss?

    Zum Beispiel

    select

    bla, substring(bla, 1, 10) = ''test'')

    where

    bla = ''irgendwas''

    Hab da leider nichts gefunden im Stil eins Escape-Characters oder sowas, wie es das glaub auch in C# gibt...

    Freitag, 3. Mai 2019 08:49

Antworten

  • Nun ja, SQL ist eher eine statische Angelegenheit. Mit dynmaic tut man sich immer mal schwer.
    Allerdings kann man eben mit sp_executesql (siehe link und Beispiel im Link) String und sonstige Konstanten als Parameter "... @ParmName ..." verwenden.
    Zu beachten ist leider nur, dass Parameter nur da erlaubt sind, wo Konstanten verwendet werden dürfen.
    Felder und Tabellen müssen im String zusammengebaut werden.

    DECLARE @IntVariable int;  
    DECLARE @SQLString nvarchar(500);  
    DECLARE @ParmDefinition nvarchar(500);  
      
    /* Build the SQL string one time.*/  
    SET @SQLString =  
         N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID  
           FROM AdventureWorks2012.HumanResources.Employee   
           WHERE BusinessEntityID = @BusinessEntityID';  
    SET @ParmDefinition = N'@BusinessEntityID tinyint';  
    /* Execute the string with the first parameter value. */  
    SET @IntVariable = 197;  
    EXECUTE sp_executesql @SQLString, @ParmDefinition,  
                          @BusinessEntityID = @IntVariable;  
    /* Execute the same string with the second parameter value. */  
    SET @IntVariable = 109;  
    EXECUTE sp_executesql @SQLString, @ParmDefinition,  
                          @BusinessEntityID = @IntVariable

    Wichtig ist halt sowohl die Typdeklaration als auch eben der Parameterwert.

    Aber warum eigentlich immer den Server selber bemühen wenn du das auf dem Client mit Parametern doch selber kannst?
    Bei sp_executesql, oder auch grundsätzlich bei execute, ist die Anzahl der Parameter ja nicht variabel, da man hier alles hart kodieren muss.

    Also verlege die Aufgabe des SQL-bauens in den Client, da kannst du
    a) den SQL so dynamisch gestalten wie nötig
    b) Parameter mit "?" oder je nach Unterstützung auch mit "@ParmName" definieren

    Beim Ausführen gibt man die Parameter in einer eignen Liste an (ParameterCollection) und die ganze Arie mit Typanpassung, Hochkommaverdoppelung, DatumZeit-Formaten usw. übernimmt der Treiber selber.

    • Als Antwort markiert darkchanter Freitag, 3. Mai 2019 14:36
    Freitag, 3. Mai 2019 12:45

Alle Antworten

  • In welcher Sprache?

    I.d.R. kann man mit Command-Objekten und Parametern arbeiten (was i.Ü. absolut zu empfehlen ist), Beispiel .Net:

    MyCommand.CommandText = "Select ... from MyTable where bla = ?";
    oder
    MyCommand.CommandText = "Select ... from MyTable where bla = @Param1";

    Für jeden Parameter sind dann Parameterobjekte zu erstellen.
    Zur Ausführungszeit füllt man die Parameter und lässt das CommandObjekt seine Arbeit tun.
    Wieder bei .Net:

    myreader = MyCommand.ExecuteReader();


    Freitag, 3. Mai 2019 09:33
  • Oh, ich meine im SQL-Server selbst, also T-SQL.

    Freitag, 3. Mai 2019 09:36
  • Hi,

    ich denke mal, Du kommst dann nicht drumrum, eben nicht direkt mit dynamischem T-SQL zu arbeiten, da es da außer Parametern nichts gibt, was Du nehmen könntest.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Freitag, 3. Mai 2019 09:47
    Moderator
  • Für T-SQL gibt es den sp_executesql, der wiederum Parameter erlaubt:
    https://docs.microsoft.com/de-de/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-2017


    Freitag, 3. Mai 2019 10:59
  • Das mit den Parametern ist schon mal eine Hilfe. Mich nerven halt noch ein bisschen die Literale. Somit vor allem der Umstand, dass ich das SQL-Statement nicht direkt benutzen kann, sondern die vielen Extra-Appostrophs einfügen muss.

    Bsp:

    select

    irgendwas, nochwas + ' (' + dasHier + ')' as bla

    where das = 'dies'

    Wär halt schön gewesen, wenn hier hier mit einem Escape-Zeichne den SQL-String hätte einbetten können.

    Hintergrund: Für dynamische Pivots kenne ich keine andere Möglichkeit, als den String zu bauen mit der Werteliste. So fand ich das auch auf diversen Web-Seiten. Staune auch, dass es keine $Values oder sowas gibt wie beim Merge-Statement.

    Freitag, 3. Mai 2019 11:10
  • Nun ja, SQL ist eher eine statische Angelegenheit. Mit dynmaic tut man sich immer mal schwer.
    Allerdings kann man eben mit sp_executesql (siehe link und Beispiel im Link) String und sonstige Konstanten als Parameter "... @ParmName ..." verwenden.
    Zu beachten ist leider nur, dass Parameter nur da erlaubt sind, wo Konstanten verwendet werden dürfen.
    Felder und Tabellen müssen im String zusammengebaut werden.

    DECLARE @IntVariable int;  
    DECLARE @SQLString nvarchar(500);  
    DECLARE @ParmDefinition nvarchar(500);  
      
    /* Build the SQL string one time.*/  
    SET @SQLString =  
         N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID  
           FROM AdventureWorks2012.HumanResources.Employee   
           WHERE BusinessEntityID = @BusinessEntityID';  
    SET @ParmDefinition = N'@BusinessEntityID tinyint';  
    /* Execute the string with the first parameter value. */  
    SET @IntVariable = 197;  
    EXECUTE sp_executesql @SQLString, @ParmDefinition,  
                          @BusinessEntityID = @IntVariable;  
    /* Execute the same string with the second parameter value. */  
    SET @IntVariable = 109;  
    EXECUTE sp_executesql @SQLString, @ParmDefinition,  
                          @BusinessEntityID = @IntVariable

    Wichtig ist halt sowohl die Typdeklaration als auch eben der Parameterwert.

    Aber warum eigentlich immer den Server selber bemühen wenn du das auf dem Client mit Parametern doch selber kannst?
    Bei sp_executesql, oder auch grundsätzlich bei execute, ist die Anzahl der Parameter ja nicht variabel, da man hier alles hart kodieren muss.

    Also verlege die Aufgabe des SQL-bauens in den Client, da kannst du
    a) den SQL so dynamisch gestalten wie nötig
    b) Parameter mit "?" oder je nach Unterstützung auch mit "@ParmName" definieren

    Beim Ausführen gibt man die Parameter in einer eignen Liste an (ParameterCollection) und die ganze Arie mit Typanpassung, Hochkommaverdoppelung, DatumZeit-Formaten usw. übernimmt der Treiber selber.

    • Als Antwort markiert darkchanter Freitag, 3. Mai 2019 14:36
    Freitag, 3. Mai 2019 12:45