Quais são as vantagens de usar os construtores de consultas SQL?

17

Existem vantagens em usar um construtor de consultas, em vez de usar SQL bruto?

Por exemplo

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

vs:

SELECT * FROM posts WHERE ...

Vejo que muitas estruturas usam esse tipo de camada de abstração, mas não entendo os benefícios.

Anna K.
fonte
Eu acho que se deve escrever consultas contra pontos de vista e não contra tabelas. Costumo pensar que as pessoas que usam criadores de consultas tendem a não escrever visualizações ou pedir aos DBAs para criá-las para eles. Ao fazer isso, eles não aproveitam todo o poder do RDBMS.
Tulains Córdova 02/02
1
@ user61852: Além de, possivelmente, alguma segurança e filtragem de graça, o que as consultas nas visualizações fornecem que as consultas nas tabelas também não podem fornecer?
Robert Harvey
4
@RobertHarvey A mesma coisa que programar para interfaces em vez de classes concretas. Desacoplamento e flexibilidade. O design das tabelas subjacentes pode acontecer desde que o "contrato", a visualização, continue "simulando" as mesmas colunas de sempre.
Tulains Córdova 02/02
@ user61852 É justo.
Robert Harvey
@RobertHarvey Transformei isso em uma resposta.
Tulains Córdova 02/02

Respostas:

20

A abstração de escrever o SQL através de uma estrutura também é resumida.

Escrever o SQL manualmente não é tão ruim por si só, mas você começa a ter problemas com a fuga e a higienização, e isso se transforma em uma confusão. Uma camada de abstração pode cuidar de tudo isso nos bastidores, permitindo que seu código seja limpo e livre de muitas mysql_real_escape_string()chamadas ou similares.

Além disso, isso traz a possibilidade de contabilizar diferentes dialetos do SQL. Nem todos os bancos de dados são criados da mesma forma e pode haver variações nas palavras-chave ou na sintaxe de uma determinada funcionalidade. O uso de uma camada de abstração permite gerar dinamicamente a sintaxe correta para sua variante.

Embora uma camada de abstração possa introduzir um impacto no desempenho, geralmente é insignificante se comparada à limpeza e robustez do código que você recebe em troca.


fonte
1
Eu não acho que os dialetos SQL diferem entre RDBMSes. E em PHP há DOP que faz a higienização para u
Anna K.
12
Os dialetos SQL diferem, é por isso que são chamados de dialetos. Quanto à DOP, a camada de abstração simplesmente oculta essa bagunça de nós.
@GlennNelson Anna significava qualquer um dialeto, usando diferentes backends (PSQL / MySQL / SQLite ...)
Izkata
2
@AnnaK. O dialeto pode não mudar, mas às vezes os recursos são diferentes. Por exemplo, o MySQL (com o mecanismo MyISAM) não suporta restrições de chave estrangeira, enquanto o PostGres. Ou o dialeto terá que lidar com tal coisa em si (que requer conhecimento completo da estrutura de dados, como o Django ORM), ou, mais provavelmente: o usuário deve ser inteligente sobre como usá-lo, o que pode fazer com que pareça como o dialeto muda, dependendo das circunstâncias.
precisa saber é
1
+1 por permitir que uma ferramenta bem construída escape e desinfete por você. Se também pode validar, é ainda melhor.
Dan Ray
11

Os construtores de consultas são um ódio para mim, tanto que escrevi meu próprio Framework (Apeel) para evitar usá-los!

Se você usa o DOP (o que eu definitivamente recomendo), a santificação da entrada é feita para você.

Como alguém já disse, embora facilite a alternância entre bancos de dados, eles tendem a suportar a funcionalidade "Menor denominador comum" e não suportam ou têm desempenho inferior para recursos mais avançados.

Desenvolvo sistemas com bancos de dados desde 1986 e, durante todo esse tempo, raramente encontrei uma empresa alterando o banco de dados que eles usam, exceto quando precisavam de melhor desempenho. Se você estiver alterando os bancos de dados para obter melhor desempenho, faz muito mais sentido gastar seu tempo otimizando manualmente suas consultas para obter o melhor proveito do novo banco de dados, em vez de receber o resultado de um construtor de consultas por uma questão de simplicidade.

O tempo gasto para se familiarizar com os qwirks de um construtor de consultas (depois aprendendo novamente quando você muda para um melhor) seria muito mais produtivamente gasto aprendendo a otimizar seu SQL.

De qualquer forma, é por isso que NÃO usar um, algumas pessoas os amam.

Gerador de código PHP
fonte
4

Teoricamente? Sim. Glenn Nelson apontou como eles frequentemente o ajudarão. (Se for um bom construtor de consultas).

Na prática? Nem sempre cumpre a teoria e pode realmente causar problemas. Suponha que você esteja usando um construtor de consultas em relação a alguns DBMS populares e tudo esteja um pouco complicado. Em seguida, um cliente solicita que você acesse o DBMS que possui algumas peculiaridades que o construtor de consultas escolhido simplesmente não consegue lidar. (Encontrei esse problema quando tive que trabalhar com uma versão mais antiga do Pervasive.)

MAS! O que você absolutamente deve fazer é separar a camada de acesso a dados e garantir a troca por uma nova, se necessário. Dessa forma, você pode criar um construtor de consultas bacana com todos os recursos, mas se precisar conectar um novo que use esse pseudo-sql ímpar para o banco de dados em questão.

ElGringoGrande
fonte
2
Algo como a situação peculiar do banco de dados não deveria ser resolvido com antecedência? Quero dizer, descobrir qual DB seu cliente está usando e escolher as estruturas / bibliotecas apropriadas de acordo é algo que deve ser tratado antes de você escrever uma única linha de código.
3

Eu acho que o benefício prático do dia a dia do construtor de consultas - é a reutilização de código e a capacidade de seguir o princípio DRY.

Com o construtor de consultas, você pode colocar partes repetidas do SQL em métodos. E, em seguida, use esses métodos para compor SQL complexo. Um exemplo seria, por exemplo, a cláusula reutilizável JOIN:

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

Portanto, o uso seria:

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

Como você pode observar - com o construtor de consultas, você pode adicionar partes do SQL em qualquer ordem (por exemplo, parte JOIN após WHERE), em contraste com o caso em que você coleta manualmente a string SQL. Além disso, você pode ler sobre o padrão do construtor para ver suas intenções e benefícios.

Concordo em escapar e higienizar, mas isso também pode ser alcançado sem o construtor de consultas. Em relação à abstração do tipo DB / dialeto - esse é um benefício bastante teórico e questionável, quase nunca utilizado na prática.

GerKirill
fonte
Para mim, este também é um benefício principal. Outra é que, com a abstração dos métodos, você pode dar aos métodos nomes mais significativos e até criar uma Linguagem Específica de Domínio a partir disso, tornando a intenção muito mais clara. Você também pode passar o construtor de consultas e permitir que diferentes componentes adicionem os bits específicos a ele. Por último, mas não menos importante, achei que me permitia encapsular padrões por trás de métodos com nomes significativos ... Encontrei alguns construtores de consultas onde a adição de colunas substitui estupidamente as anteriores, o que meio que torna muitas das coisas acima inúteis ...
malte
2

fornecerei uma resposta com base no arquivo leia-me de um construtor SQL personalizado meu ( Dialeto )

(texto simples a seguir, referências específicas da biblioteca removidas)

Exigências

  1. Suporte a vários fornecedores de banco de dados (por exemplo: MySQL, PostgreSQL, SQLite, MS SQL / SQL Server, Oracle, DB2, ..)
  2. Ampliado facilmente para novos bancos de dados (de preferência através de uma configuração independente da implementação)
  3. Modularidade e transferibilidade independente da implementação
  4. API flexível e intuitiva

Recursos

  1. modelos baseados em gramática
  2. suporte a visualizações flexíveis personalizadas
  3. abstração de db, modularidade e transferibilidade
  4. modelos preparados
  5. escape de dados

Eu acho que os recursos e requisitos acima esboçam as razões pelas quais alguém usaria um construtor de abstração SQL

A maioria dos recursos acima é suportada pela maioria dos construtores SQL (embora eu não pense que todos os listados sejam suportados, que eu saiba)

Exemplos de casos de uso:

  1. Plataforma CMS capaz de funcionar (sem alteração do código subjacente) com vários fornecedores de banco de dados
  2. Código de aplicativo personalizado, onde o fornecedor do banco de dados está apto a alterar e / ou os esquemas de dB são dinâmicos (isso significa que muitas consultas não podem ser codificadas por código, mas ainda precisam ser abstraídas o suficiente para que o código seja robusto às alterações)
  3. Prototipagem com outro banco de dados que não seja usado na produção (exigiria uma base de código duplicada pelo menos para parte do código)
  4. O código do aplicativo não está totalmente acoplado ao provedor e / ou implementação de banco de dados específicos (mesmo dentro do mesmo fornecedor de banco de dados, por exemplo, versões diferentes do fornecedor de banco de dados), portanto, é mais robusto, flexível e modular
  5. Muitos casos comuns de consultas e escape de dados são tratados pela própria estrutura e, geralmente, isso é ótimo e mais rápido

Finalmente, um exemplo de um caso de uso que eu tinha. Eu estava construindo um aplicativo em que o esquema de banco de dados subjacente (wordpress) não era adequado para o tipo de consulta de dados que precisava ser feita, além de que algumas tabelas WP (por exemplo, postagens) precisavam ser usadas (portanto, tabelas completamente novas para todos os dados do aplicativo não era uma opção).

Nesse caso, ser capaz de criar um aplicativo semelhante ao MVC, onde o modelo poderia ser consultado por condições personalizadas / dinâmicas, tornou a consulta codificada em código quase um pesadelo. Imagine ter que suportar a consulta de talvez de duas a três tabelas com junções e filtrar as condições para ver qual tabela se unir e também cuidar dos aliases necessários e assim por diante.

Claramente, esse era um caso de uso de abstração de consulta e, ainda mais, era necessário (ou pelo menos muito beneficiado) ter a capacidade de definir visualizações flexíveis personalizadas (um conglomerado de tabelas unidas como se fossem uma tabela personalizada adequada para o modelo) . Então ficou muito mais fácil, limpo, modular e flexível. Em outro aspecto, o aplicativo (código) também usou a camada de abstração de consulta como uma ferramenta de normalização (esquema db) . Como alguns dizem, era à prova de futuro .

Se, amanhã, as pessoas decidirem que precisam de algumas opções ou dados extras, é muito fácil adicionar isso ao modelo em algumas linhas e funcionar bem. Além disso, se, amanhã, as pessoas decidirem que não querem mais usar o wordpress (como o aplicativo é fracamente acoplado ao wordpress como um plug-in), também é relativamente fácil alterar ( apenas a definição ) dos modelos em algumas linhas de código para se adaptar ao novo esquema.

Veja o que eu quero dizer?

Nikos M.
fonte
1

Muitas vezes, alguns dos argumentos para essas consultas são de fato alguns valores e não constantes. Agora, muitos deles foram essencialmente derivados de postagens de formulários do usuário. E, portanto, existem muitas possibilidades para ataques de injeção de SQL. Portanto, a formação de consultas inerentemente requer validação completa.

Agora, isso não quer dizer que não confiamos no desenvolvedor, mas a formação da consulta pode ser fácil, mas repetir todas as verificações de validação possíveis em todos os lugares pode implicar que você pode perder algumas vezes acidentalmente ou modificar a consulta, mas não modifica a consulta, mas não atualize a verificação de validação. Algum novato pode até conhecer todos os perigos de perder isso. Portanto, a abstração do construtor de consultas é bastante essencial.

Dipan Mehta
fonte
0

Eu costumava pensar que os construtores de consultas eram aplicativos da GUI que permitiam selecionar tabelas e fazer junções graficamente enquanto gerava o SQL, mas agora entendo que você também chama os construtores de consultas de APIs que fornecem uma maneira de não precisar criar consultas SQL puras , abstraindo-se das possíveis diferenças nos sabores do SQL.

O uso desses criadores de consultas é bom , mas costumo pensar que as pessoas que dependem muito deles tendem a não perguntar aos DBAs: "ei, essa é uma consulta que eu uso muito, por favor, crie uma visão a partir dela".

Não me interpretem mal.

Eu acho que você deve escrever consultas contra pontos de vista e não tabelas. Não por segurança ou filtragem, que são boas razões, mas pela mesma razão, você deve codificar contra interfaces e não contra classes concretas: desacoplamento. As visualizações são como "contratos", da mesma forma que as interfaces são "contratos" no OOP. Você pode alterar as tabelas subjacentes, mas contanto que force as exibições a mostrar o mesmo "contrato" para os programadores, o código não deve ser interrompido.

Mais uma vez, não me interpretem mal, você pode usar os construtores de consultas para consultar visualizações, mas muitas visualizações existem como um processo de maduração que é o produto de ter que escrever consultas e perguntar ao seu DBA: "cara, crie isso, por favor" .

Estou errado ao pensar que, ao não escrever consultas, você falha em detectar a necessidade de criar determinadas visualizações?

Outra coisa que me preocupa são os programadores iniciantes que não dominam o SQL, uma das mais belas peças de tecnologia criadas pelo homem, por não ter que fazer isso.

Tulains Córdova
fonte
Que tal um DBA que diz: "Esta consulta está com problemas, vamos trabalhar juntos e melhorá-la". Pode ter funcionado muito bem no começo, mas agora está tendo problemas. Se tudo o que é necessário é um índice, por que incomodar o desenvolvedor com isso?
JeffO 02/02
Essa é uma situação totalmente diferente e está perfeitamente bem.
Tulains Córdova 02/02
Eu sinto vontade de envolver o DBA toda vez que uma consulta extrai um único registro de uma tabela ou exibição cria um gargalo no processo de desenvolvimento.
JeffO 02/02