Jakie są zalety korzystania z konstruktorów zapytań SQL?


17

Czy są jakieś zalety używania konstruktora zapytań zamiast używania surowego SQL?

Na przykład

$q->select('*')
  ->from('posts')
  ->innerJoin('terms', 'post_id')
  ->where(...)

vs:

SELECT * FROM posts WHERE ...

Widzę, że wiele frameworków używa tego rodzaju warstw abstrakcji, ale nie rozumiem korzyści.


Myślę, że należy pisać zapytania przeciwko widokom, a nie tabelom. Wydaje mi się, że ludzie używający konstruktorów zapytań zwykle nie piszą widoków ani nie proszą DBA o ich utworzenie. Czyniąc to, nie wykorzystują całej mocy RDBMS.
Tulains Córdova

1
@ user61852: Co więcej niż niektóre zabezpieczenia i filtrowanie za darmo, jakie zapytania dotyczące widoków mogą zapewnić, że zapytania dotyczące tabel również nie mogą zapewnić?
Robert Harvey

4
@RobertHarvey To samo, co programowanie interfejsów zamiast konkretnych klas. Oddzielenie i elastyczność. Konstrukcja leżących u podstaw tabel może być przypadkowa, dopóki „kontrakt”, widok, pozostaje „symulując” te same kolumny jak zawsze.
Tulains Córdova

@ user61852 Wystarczająco uczciwy.
Robert Harvey

@RobertHarvey Zamieniłem to w odpowiedź.
Tulains Córdova

Odpowiedzi:


20

Abstrakty pisania SQL za pomocą studni szkieletowej, abstrakty.

Ręczne pisanie SQL nie jest wcale takie złe, ale zaczynasz mieć problemy z ucieczką i odkażaniem, co zamienia się w bałagan. Warstwa abstrakcji może zająć się tym wszystkim za kulisami, dzięki czemu Twój kod będzie czysty i wolny od wielu mysql_real_escape_string()połączeń itp.

Dodatkowo daje to możliwość rozliczania różnych dialektów SQL. Nie wszystkie bazy danych są zbudowane tak samo i mogą występować różnice w słowach kluczowych lub składni niektórych funkcji. Korzystanie z warstwy abstrakcji umożliwia dynamiczne generowanie poprawnej składni dla wariantu.

Podczas gdy warstwa abstrakcji może wprowadzić obniżenie wydajności, jest ona zasadniczo nieistotna w porównaniu z czystością i odpornością kodu otrzymywanego w zamian.


1
Nie sądzę, że dialekty SQL różnią się między RDBMS. A w PHP jest ChNP, który wykonuje dezynfekcję dla ciebie
Anna K.

12
Dialekty SQL różnią się, dlatego nazywane są dialektami. Jeśli chodzi o PDO, warstwa abstrakcji po prostu ukrywa przed nami ten bałagan.

@GlennNelson Anna miał na myśli dowolny dialekt, używając różnych backendów (PSQL / MySQL / SQLite ...)
Izkata

2
@AnnaK. Dialekt może się nie zmieniać, ale czasami funkcje są różne. Na przykład MySQL (z silnikiem MyISAM) nie obsługuje ograniczeń klucza obcego, podczas gdy PostGres tak. Albo dialekt będzie musiał poradzić sobie z taką rzeczą (co wymaga pełnej wiedzy o strukturze danych, tak jak robi to w Django ORM), lub, co bardziej prawdopodobne: użytkownik musi być inteligentny w tym, jak go używa, co może sprawić, że będzie wyglądać jak zmiany dialektu, w zależności od okoliczności.
Izkata

1
+1 za pozwolenie, aby dobrze zbudowane narzędzie uciekało i odkażyło za ciebie. Jeśli może to zrobić także sprawdzanie poprawności, to jeszcze lepiej.
Dan Ray

11

Konstruktorzy zapytań są moją ulubioną nienawiścią, dlatego napisałem własną platformę (Apeel), aby ich nie używać!

Jeśli używasz PDO (co zdecydowanie polecam), santising danych wejściowych jest obsługiwany za Ciebie.

Jak ktoś powiedział, chociaż ułatwiają przełączanie między bazami danych, zwykle obsługują funkcję „najniższego wspólnego mianownika” i albo nie obsługują, albo mają gorszą wydajność w przypadku bardziej zaawansowanych funkcji.

Tworzę systemy z bazami danych od około 1986 roku i przez cały ten czas rzadko spotykałem firmę, która faktycznie zmienia bazę danych, z której korzystają, inaczej niż wtedy, gdy potrzebowała lepszej wydajności. Jeśli zmieniasz bazy danych w celu uzyskania lepszej wydajności, sensowniej jest spędzać czas na ręcznym optymalizowaniu zapytań, aby uzyskać jak najwięcej z nowej bazy danych, zamiast korzystać z konstruktora zapytań dla uproszczenia.

Czas spędzony na opanowaniu qwirków konstruktora zapytań (a następnie ponownej nauki po przejściu na lepszą) byłby o wiele bardziej produktywnie spędzony na nauce optymalizacji SQL.

W każdym razie dlatego NIE należy go używać, niektórzy ludzie je jednak kochają.


4

Teoretycznie Tak. Glenn Nelson wskazał, jak często ci pomogą. (Jeśli jest to dobry konstruktor zapytań).

W praktyce? Nie zawsze odpowiada teorii i może powodować problemy. Załóżmy, że używasz konstruktora zapytań przeciwko niektórym popularnym DBMS i wszystko jest brzoskwiniowe. Następnie klient prosi, abyś uderzył w swój DBMS, który ma pewne dziwactwa, których wybrany kreator zapytań po prostu nie jest w stanie obsłużyć. (Uderzyłem ten problem, gdy musiałem pracować ze starszą wersją Pervasive).

ALE! To, co powinieneś absolutnie zrobić, to oddzielić warstwę dostępu do danych i upewnić się, że możesz w razie potrzeby zamienić ją na nową. W ten sposób możesz stworzyć ten fajny konstruktor zapytań ze wszystkimi funkcjami, ale jeśli chcesz podłączyć nowy, który używa tego nieparzystego pseudo-sql dla danej bazy danych.


2
Czy coś takiego jak dziwactwo DB nie powinno być wcześniej rozwiązane? Chodzi mi o to, aby dowiedzieć się, jakiej bazy danych używa Twój klient i odpowiednio wybrać odpowiednie frameworki / biblioteki. Jest to coś, co powinno być obsłużone przed napisaniem pojedynczego wiersza kodu.

3

Myślę, że praktyczną, codzienną zaletą konstruktora zapytań - jest ponowne użycie kodu i umiejętność przestrzegania zasady DRY.

Za pomocą konstruktora zapytań możesz umieszczać powtarzające się części SQL w metodach. A następnie użyj tych metod, aby skomponować złożony SQL. Przykładem może być np. Klauzula JOIN wielokrotnego użytku:

function joinTaskWithClient($queryBuilder) {
    $queryBuilder->join('task', 'contract', 'task.contract_id = contract.id')
                 ->join('contract', 'client', 'contract.client_id = client.id');
}

Zatem użycie byłoby:

$queryBuilder->select('client.name')
             ->from('client')
             ->where('task.id=:task')->setParameter('task', 42);
joinTaskWithClient($queryBuilder);

Jak można zauważyć - za pomocą konstruktora zapytań można dodawać części SQL w dowolnej kolejności (np. ŁĄCZYĆ część po GDZIE), w przeciwieństwie do przypadku, gdy ręcznie zbiera się ciąg SQL. Możesz także przeczytać o wzorcu konstruktora, aby zobaczyć jego zamiary i zalety.

Zgadzam się na ucieczkę i odkażanie, ale można to również osiągnąć bez konstruktora zapytań. Odnośnie abstrakcji typu DB / dialektu - jest to dość teoretyczna i wątpliwa korzyść, rzadko stosowana w praktyce.


Dla mnie jest to również główna korzyść. Innym jest to, że dzięki abstrakcji na metody można nadać tym metodom bardziej znaczące nazwy, a nawet stworzyć z nich język specyficzny dla domeny, dzięki czemu intencja jest znacznie bardziej wyraźna. Możesz także przekazać kreator zapytań i pozwolić różnym komponentom dodać do niego określone bity. Wreszcie odkryłem, że pozwoliło mi to zawrzeć wzorce kryjące się za metodami o znaczących nazwach ... Znalazłem kilka konstruktorów zapytań, w których dodawanie kolumn głupio nadpisało wcześniejsze, co sprawia, że ​​wiele z powyższych bezużytecznych ...
malte

2

podam odpowiedź na podstawie pliku readme mojego niestandardowego konstruktora SQL ( Dialect )

(następuje zwykły tekst, usunięte odwołania specyficzne dla biblioteki)

Wymagania

  1. Obsługa wielu dostawców DB (np. MySQL, PostgreSQL, SQLite, MS SQL / SQL Server, Oracle, DB2, ..)
  2. Łatwo rozszerzony na nowe bazy danych (najlepiej poprzez ustawienie konfiguracji niezależne od implementacji)
  3. Modułowość i niezależność od implementacji możliwości przenoszenia
  4. Elastyczny i intuicyjny interfejs API

cechy

  1. szablony oparte na gramatyce
  2. obsługa niestandardowych widoków miękkich
  3. abstrakcja db, modułowość i możliwość przenoszenia
  4. przygotowane szablony
  5. ucieczka danych

Myślę, że powyższe funkcje i wymagania szkicują powody, dla których warto użyć konstruktora abstrakcji SQL

Większość powyższych funkcji jest obsługiwana przez większość konstruktorów SQL (choć nie sądzę, że wszystkie wymienione są obsługiwane, o ile wiem)

Przykłady przypadków użycia:

  1. Platforma CMS może współpracować (bez zmiany kodu bazowego) z wieloma dostawcami DB
  2. Niestandardowy kod aplikacji, w którym dostawca DB może się zmieniać i / lub schematy dB są dynamiczne (oznacza to, że wiele zapytań nie może być zakodowanych na stałe, ale nadal musi być wystarczająco abstrakcyjnych, aby kod był odporny na zmiany)
  3. Prototypowanie przy użyciu innej bazy danych niż ta używana w produkcji (wymagałoby duplikacji bazy kodu przynajmniej dla części kodu)
  4. Kod aplikacji nie jest ściśle powiązany z konkretnym dostawcą DB i / lub implementacją (nawet w obrębie tego samego dostawcy DB, np. Różnych wersji dostawcy DB), dlatego jest bardziej niezawodny, elastyczny i modułowy
  5. Wiele zwykłych przypadków zapytań i ucieczki danych jest obsługiwanych przez samą strukturę i zwykle jest to zarówno optymalne, jak i szybsze

W końcu przykład przypadku, który miałem. budowałem aplikację, w której bazowy schemat DB (wordpress) nie był dobrze dopasowany do rodzaju zapytań o dane, które należało wykonać, a także niektóre tabele WP (np. posty) musiały zostać użyte (więc mając zupełnie nowe tabele dla wszystkich danych aplikacji nie było opcją).

W takim przypadku możliwość stworzenia aplikacji podobnej do MVC, w której model mógłby być sprawdzany w niestandardowych / dynamicznych warunkach, sprawił, że zapytania stały się niemal koszmarem. Wyobraź sobie, że potrzebujesz obsługi zapytań może do 2-3 tabel z łączeniami i filtrowania warunków, aby zobaczyć, z którą tabelą się połączyć, a także zadbać o wymagane aliasy i tak dalej.

Najwyraźniej był to przypadek użycia abstrakcji zapytania, a co więcej, wymagał (lub przynajmniej znacznie skorzystał) z możliwości definiowania niestandardowych widoków miękkich (konglomerat połączonych tabel, tak jakby były one jedną niestandardową tabelą odpowiednią dla modelu) . Wtedy było o wiele łatwiejsze, czystsze, modułowe i elastyczne. W innym aspekcie aplikacja (kod) również używała warstwy abstrakcji zapytania jako narzędzia normalizacyjnego (schematu db) . Jak niektórzy twierdzą, był on przyszłościowy .

Jeśli jutro ludzie zdecydują, że potrzebują dodatkowych opcji lub danych, bardzo łatwo można dodać to do modelu w kilku liniach i działać dobrze. Dodatkowo, jeśli jutro ludzie zdecydują, że nie chcą już używać wordpressa (ponieważ aplikacja jest luźno powiązana z wordpressem jako wtyczką), można go również stosunkowo łatwo zmienić ( tylko definicja ) modeli w kilku liniach kodu w celu dostosowania do nowego schematu.

Widzisz co mam na myśli?


1

Dość często niektórymi argumentami za tymi zapytaniami są pewne wartości, a nie stałe. Obecnie wiele z nich pochodzi głównie z postów użytkowników. Dlatego istnieje wiele możliwości ataków typu SQL injection. Zatem z natury tworzenie zapytań wymaga pełnej weryfikacji.

Nie oznacza to jednak, że nie ufamy programistom, ale tworzenie zapytań może być łatwe, ale powtórzenie wszystkich możliwych kontroli sprawdzania poprawności wszędzie może po prostu sugerować, że możesz czasami pominąć przypadkowo lub zmodyfikować zapytanie, ale nie modyfikuj zapytania, ale nie zaktualizuj sprawdzanie poprawności. Niektórzy nowicjusze mogą nawet wiedzieć o wszystkich niebezpieczeństwach pominięcia tego. Dlatego abstrakcja konstruktora zapytań jest dość istotna.


0

Kiedyś myślałem, że konstruktory zapytań to aplikacje GUI, które pozwalały ci wybierać tabele i łączyć się graficznie podczas generowania SQL pod maską, ale teraz rozumiem, że wywołujesz również konstruktorów zapytań API, które zapewniają sposób, że nie musisz tworzyć czystych zapytań SQL , więc pozbywając się potencjalnych różnic w smakach SQL.

Korzystanie z takich konstruktorów zapytań jest dobre , ale wydaje mi się, że ludzie, którzy w dużym stopniu na nich polegają, nie pytają DBA: „hej, to jest pytanie, którego często używam, proszę utworzyć z niego widok”.

Nie zrozum mnie źle.

Myślę, że powinieneś pisać zapytania dotyczące widoków, a nie tabel. Nie ze względów bezpieczeństwa lub filtrowania, które są dobre powody, ale z tego samego powodu powinieneś kodować przeciwko interfejsom, a nie konkretnym klasom: oddzielenie. Widoki są jak „kontrakty”, tak samo jak interfejsy są „kontraktami” w OOP. Możesz zmienić podstawowe tabele, ale dopóki zmusisz widoki do pokazywania programistom tej samej „umowy”, kod nie powinien się zepsuć.

Znowu, nie zrozum mnie źle, możesz używać konstruktorów zapytań do tworzenia zapytań do widoków, ale powstaje wiele widoków jako proces maduracji, który jest wynikiem konieczności pisania zapytań i zadawania DBA: „stary, utwórz to, proszę” .

Czy mylę się myśląc, że nie pisząc zapytań, nie wykrywasz potrzeby tworzenia określonych widoków?

Inna sprawa, która mnie niepokoi, to początkujący programiści, którzy nie opanowali SQL, jednego z najpiękniejszych kawałków technologii stworzonych przez człowieka, ponieważ nie musieli tego robić.


Co powiesz na DBA, który mówi: „To zapytanie działa nieprawidłowo, pracujmy razem i popraw go”. Może na początku działało dobrze, ale teraz występują problemy. Jeśli wszystko, czego potrzeba, to indeks, po co zawracać sobie tym głowy programistą?
JeffO,

To zupełnie inna sytuacja i jest całkowicie OK.
Tulains Córdova

Po prostu mam ochotę zaangażować DBA za każdym razem, gdy zapytanie wyciąga pojedynczy rekord z tabeli lub widoku, co powoduje wąskie gardło w procesie programowania.
JeffO,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.