Todos nós que trabalhamos com bancos de dados relacionais aprendemos (ou estamos aprendendo) que o SQL é diferente. Obter os resultados desejados e fazê-lo com eficiência envolve um processo tedioso, parcialmente caracterizado por aprender paradigmas desconhecidos e descobrir que alguns de nossos padrões de programação mais familiares não funcionam aqui. Quais são os antipadrões comuns que você já viu (ou se comprometeu)?
sql
anti-patterns
maior
fonte
fonte
Respostas:
Estou constantemente decepcionado com a tendência da maioria dos programadores de misturar sua lógica de interface do usuário na camada de acesso a dados:
Normalmente, os programadores fazem isso porque pretendem vincular seus conjuntos de dados diretamente a uma grade, e é conveniente ter o formato SQL Server do lado do servidor do que o formato no cliente.
Consultas como a mostrada acima são extremamente frágeis porque acoplam firmemente a camada de dados à camada da interface do usuário. Além disso, esse estilo de programação impede completamente que os procedimentos armazenados sejam reutilizáveis.
fonte
Aqui estão os meus 3 principais.
Número 1. Falha ao especificar uma lista de campos. (Editar: para evitar confusão: esta é uma regra de código de produção. Ela não se aplica a scripts de análise únicos - a menos que eu seja o autor.)
deveria estar
Número 2. Usando um cursor e um loop while, quando um loop while com uma variável loop for suficiente.
Número 3. DateLogic através dos tipos de string.
Deveria estar
Vi um pico recente de "Uma consulta é melhor que duas, certo?"
Essa consulta requer dois ou três planos de execução diferentes, dependendo dos valores dos parâmetros. Apenas um plano de execução é gerado e preso no cache para este texto sql. Esse plano será usado independentemente do valor dos parâmetros. Isso resulta em baixo desempenho intermitente. É muito melhor escrever duas consultas (uma consulta por plano de execução pretendido).
fonte
Campos de senha legíveis por humanos , por exemplo. Auto-explicativo.
Usando LIKE contra colunas indexadas , estou quase tentado a dizer LIKE em geral.
Reciclando valores de PK gerados por SQL.
Surpresa, ninguém mencionou a mesa divina ainda. Nada diz "orgânico" como 100 colunas de sinalizadores de bits, grandes seqüências de caracteres e números inteiros.
Depois, há o padrão "Sinto falta de arquivos .ini" : armazenando CSVs, seqüências delimitadas por pipe ou outros dados necessários para análise em grandes campos de texto.
E para servidor MS SQL o uso de cursores em tudo . Existe uma maneira melhor de executar qualquer tarefa do cursor.
Editado porque há tantos!
fonte
LIKE '%LIKE'
.Não precisa se aprofundar: não usar instruções preparadas.
fonte
Usando aliases de tabela sem sentido:
Torna a leitura de uma instrução SQL grande muito mais difícil do que precisa
fonte
fonte
Meus insetos são as tabelas de acesso de 450 colunas que foram reunidas pelo filho de 8 anos da melhor amiga do diretor de administração e a tabela de pesquisa que só existe porque alguém não sabe como normalizar uma estrutura de dados corretamente.
Normalmente, esta tabela de pesquisa se parece com isso:
Perdi a conta do número de clientes que vi que têm sistemas que dependem de abominações como essa.
fonte
Os que eu mais não gosto são
Usando espaços ao criar tabelas, sprocs etc. Estou bem com CamelCase ou under_scores e singular ou plural e MAIÚSCULAS ou minúsculas, mas preciso me referir a uma tabela ou coluna [com espaços], especialmente se [estiver estranhamente espaçada] (sim, Eu me deparei com isso) realmente me irrita.
Dados não normalizados. Uma tabela não precisa ser perfeitamente normalizada, mas quando encontro uma tabela de funcionários que possui informações sobre sua pontuação de avaliação atual ou sobre qualquer outra coisa principal, isso me diz que provavelmente precisarei criar uma tabela separada em algum momento e tente mantê-los sincronizados. Normalizarei os dados primeiro e, em seguida, se vir um local em que a desnormalização ajuda, considerarei.
Uso excessivo de visualizações ou cursores. As visualizações têm um objetivo, mas quando cada tabela é agrupada em uma visualização, é demais. Eu tive que usar cursores algumas vezes, mas geralmente você pode usar outros mecanismos para isso.
Acesso. Um programa pode ser um antipadrão? Temos o SQL Server no meu trabalho, mas várias pessoas usam o acesso devido à sua disponibilidade, "facilidade de uso" e "simpatia" a usuários não técnicos. Há muito aqui para entrar, mas se você já esteve em um ambiente semelhante, você sabe.
fonte
use SP como o prefixo do nome do procedimento de armazenamento, porque ele primeiro procurará no local dos procedimentos do sistema, em vez dos personalizados.
fonte
Uso excessivo de tabelas e cursores temporários.
fonte
Para armazenar valores de tempo, apenas o fuso horário UTC deve ser usado. A hora local não deve ser usada.
fonte
usando @@ IDENTITY em vez de SCOPE_IDENTITY ()
Citado nesta resposta :
fonte
Reutilizar um campo "morto" para algo a que não se destinava (por exemplo, armazenar dados do usuário em um campo "Fax") - muito tentador como uma solução rápida!
fonte
e assumindo que o resultado será classificado por alguma_coluna. Eu já vi isso um pouco com a Sybase, onde a suposição se mantém (por enquanto).
fonte
Ou, amontoando tudo em uma linha.
fonte
A
FROM TableA, TableB WHERE
sintaxe para JOINS em vez deFROM TableA INNER JOIN TableB ON
Fazendo suposições de que uma consulta será retornada classificada de uma certa maneira sem inserir uma cláusula ORDER BY, apenas porque foi dessa maneira que ela apareceu durante o teste na ferramenta de consulta.
fonte
Aprendendo SQL nos primeiros seis meses de sua carreira e nunca aprendendo mais nada nos próximos 10 anos. Em particular, não aprendendo ou usando efetivamente os recursos SQL de janela / analítica. Em particular, o uso de over () e partição por.
Consulte o Apêndice A do O'Reilly SQL Cookbook para obter uma boa visão geral das funções de janelas.
fonte
Preciso colocar meu favorito atual aqui, apenas para completar a lista. Meu antipadrão favorito não está testando suas consultas .
Isso se aplica quando:
E todos os testes executados com dados atípicos ou insuficientes não contam. Se for um procedimento armazenado, coloque a instrução de teste em um comentário e salve-a com os resultados. Caso contrário, coloque-o em um comentário no código com os resultados.
fonte
Abuso temporário da tabela.
Especificamente esse tipo de coisa:
Não crie uma tabela temporária a partir de uma consulta, apenas para excluir as linhas que você não precisa.
E sim, vi páginas de código neste formulário nos bancos de dados de produção.
fonte
Visão contrária: excesso de obsessão com normalização.
A maioria dos sistemas SQL / RBDBs oferece muitos recursos (transações, replicação) que são bastante úteis, mesmo com dados não normalizados. O espaço em disco é barato e, às vezes, pode ser mais simples (código mais fácil, tempo de desenvolvimento mais rápido) manipular / filtrar / pesquisar dados buscados, do que escrever o esquema 1NF e lidar com todos os aborrecimentos nele (junções complexas, subselects desagradáveis) etc).
Descobri que os sistemas super normalizados costumam ser otimização prematura, especialmente durante os estágios iniciais de desenvolvimento.
(mais pensamentos sobre isso ... http://writeonly.wordpress.com/2008/12/05/simple-object-db-using-json-and-python-sqlite/ )
fonte
Acabei de montar este, com base em algumas das respostas SQL aqui no SO.
É um antipadrão sério pensar que os gatilhos são para bancos de dados, assim como os manipuladores de eventos são para OOP. Existe essa percepção de que qualquer lógica antiga pode ser acionada para ser acionada quando uma transação (evento) acontece em uma tabela.
Não é verdade. Uma das grandes diferenças é que os gatilhos são síncronos - com uma vingança, porque são síncronos em uma operação definida, não em uma operação de linha. No lado OOP, exatamente o oposto - os eventos são uma maneira eficiente de implementar transações assíncronas.
fonte
Procedimentos ou funções armazenados sem nenhum comentário ...
fonte
1) Não sei se é um antipadrão "oficial", mas não gosto e tento evitar literais de string como valores mágicos em uma coluna do banco de dados.
Um exemplo da tabela 'image' da MediaWiki:
(Eu só noto caixa diferente, outra coisa a evitar)
Eu projeto casos como pesquisas int em tabelas ImageMediaType e ImageMajorMime com chaves primárias int.
2) conversão de data / string que depende de configurações específicas do NLS
sem identificador de formato
fonte
Subconsultas idênticas em uma consulta.
fonte
A visão alterada - uma visão alterada com muita frequência e sem aviso ou motivo. A mudança será notada no momento mais inapropriado ou, pior, errada e nunca notada. Talvez seu aplicativo seja interrompido porque alguém pensou em um nome melhor para essa coluna. Como regra, as exibições devem estender a utilidade das tabelas base, mantendo um contrato com os consumidores. Corrija os problemas, mas não adicione recursos ou pior comportamento de alteração, pois isso cria uma nova exibição. Para mitigar, não compartilhe visualizações com outros projetos e use CTEs quando as plataformas permitirem. Se sua loja possui um DBA, você provavelmente não poderá alterar as visualizações, mas todas as suas visualizações estarão desatualizadas e / ou inúteis nesse caso.
O! Paramed - uma consulta pode ter mais de uma finalidade? Provavelmente, mas a próxima pessoa que a ler não saberá até profunda meditação. Mesmo que você não precise deles agora, é provável que sim, mesmo que seja "apenas" para depurar. A adição de parâmetros reduz o tempo de manutenção e mantém as coisas SECA. Se você tiver uma cláusula where, deverá ter parâmetros.
O caso sem CASE -
fonte
Os dois que eu mais encontro e que podem ter um custo significativo em termos de desempenho são:
Usando cursores em vez de uma expressão baseada em conjunto. Eu acho que esse ocorre com frequência quando o programador está pensando de maneira processual.
Usando subconsultas correlacionadas, quando uma associação a uma tabela derivada pode fazer o trabalho.
fonte
Colocar coisas em tabelas temporárias, especialmente as pessoas que alternam do SQL Server para o Oracle, costumam usar tabelas temporárias em excesso. Basta usar instruções de seleção aninhadas.
fonte
Desenvolvedores que escrevem consultas sem ter uma boa idéia sobre o que torna os aplicativos SQL (consultas individuais e sistemas multiusuário) rápidos ou lentos. Isso inclui ignorância sobre:
fonte
Usando o SQL como um pacote ISAM (Método de Acesso Sequencial Indexado) glorificado. Em particular, aninhando cursores em vez de combinar instruções SQL em uma única instrução, embora maior. Isso também conta como 'abuso do otimizador', pois, na verdade, não há muito que o otimizador possa fazer. Isso pode ser combinado com declarações não preparadas para máxima ineficiência:
A solução correta (quase sempre) é combinar as duas instruções SELECT em uma:
A única vantagem da versão de loop duplo é que você pode identificar facilmente as quebras entre os valores na Tabela1 porque o loop interno termina. Isso pode ser um fator nos relatórios de quebra de controle.
Além disso, a classificação no aplicativo geralmente é um não-não.
fonte
Usando chaves primárias como substitutas para endereços de registros e usando chaves estrangeiras como substitutas para ponteiros incorporados nos registros.
fonte