Pchełki SQL: cudzysłowy, cudzysłowy

https://xpil.eu/NpB8I

Natrafiłem niedawno na całkiem nudny przypadek z cudzysłowami w skrypcie T-SQL, którym - z braku jakiegoś bardziejszego laku - niniejszym dzielę się z pleno titulo czytawcami i czytajkami. A nuż się przyda.

Zaczniemy od początku:

declare @d1 date = '2021-01-01';

Proste. Deklarujemy zmienną d1, typu data, z wartością ustawioną na początek 2021 roku.

A teraz spróbujmy skonstruować dynamiczne zapytanie SQL używające ww. zmiennej i zapisać je do innej zmiennej:

declare @zapytanie nvarchar(max) = 'SELECT * FROM jakas_tabelka where jakies_pole = ''' + @d1 + ''';'

Tutaj zmienna d1 jest już otoczona płotkiem z trzech ciapków po każdej stronie, bo tak się cytuje ciapki w SQL-u (podwaja się je).

A teraz spróbujmy skonstruować dynamiczne zapytanie SQL, które będziemy uruchamiać na serwerze zdalnym za pomocą operatora OPENQUERY:

declare @openquery_sql nvarchar(max) = 'SELECT * FROM OPENQUERY([zdalny_serwer], ''SELECT * FROM jakas_tabelka where jakies_pole = ''''' + @d1 + ''''';'')'

Tutaj wokół zmiennej d1 powstał już popiątny ostrokół, ponieważ cytujemy w cytacie.

Wszystko jasne?

Nie do końca jasne? No dobra. Spróbujmy zatem pobawić się kredkami:

Oryginalne zapytanie, apostrofy wokół daty pomalowane na zielono:

declare @d1 date = '2021-01-01';

Zapytanie dynamiczne, apostrofy wokół daty nadal pomalowane na zielono, apostrofy wokół całej zmiennej - na różowo:

declare @zapytanie nvarchar(max) = 'SELECT * FROM jakas_tabelka where jakies_pole = ''' + @d1 + ''';'

Wreszcie najbardziej pozagnieżdżana wersja: cała zmienna @openquery_sql otoczona pomarańczowymi ciapkami, a zielone i różowe się rozmnożyły:

declare @openquery_sql nvarchar(max) = 'SELECT * FROM OPENQUERY([zdalny_serwer], ''SELECT * FROM jakas_tabelka where jakies_pole = ''''' + @d1 + ''''';'')'

Nie wiem jak reszta świata, ale ja tego typu zapytania zawsze tworzę metodą prób i błędów (z przewagą tych ostatnich).

https://xpil.eu/NpB8I

2 komentarze

  1. A dla nie sponiewieranych SQLem, co to są dynamiczne zapytania?

    Pytanie z perspektywy osoby, która kojarzy podstawy PHP i MySQL

    1. Dynamiczne zapytanie SQL to komenda, która nie jest zapisana bezpośrednio w kodzie źródłowym, tylko „zbudowana” przez ów kod. Weźmy na przykład funkcję PHP, która na wejście dostaje nazwę tabeli, a na wyjściu generuje jeden losowy rekord z tej tabeli:

      function getRandomRow(string $tableName, $connection): array {
          $escapedTableName = str_replace("'", "''", $tableName);
          $query = "SELECT TOP 1 * FROM [$escapedTableName] ORDER BY NEWID()";
          $stmt = sqlsrv_query($connection, $query);
          $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
          if (!$row) {
              throw new Exception("No data found or query failed.");
          }
          sqlsrv_free_stmt($stmt);
          return $row;
      }
      

      W tym przykładzie, linia:

      SELECT TOP 1 * FROM [$escapedTableName] ORDER BY NEWID()

      to jest właśnie zapytanie dynamiczne. A więc zamiast konkretnego zapytania SQL mamy tutaj wyrażenie składające się z operatorów SQL oraz lokalnych zmiennych PHP.

      Bardziej zaawansowane przykłady mogą obejmować np. włączanie lub wyłączanie całych sekcji / bloków skryptu SQL, filtrów, operatorów agregujących itd.

Leave a Comment

Komentarze mile widziane.

Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]

Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.