As diferenças podem ser sutis, às vezes importantes e às vezes efetivamente inexistentes.
Em geral, uma instrução preparada 1. é preparada com o servidor (SQL analisado, plano de execução gerado etc.), 2. é executado com os parâmetros adicionais e 3. é fechado. Ele permite que você reutilize o mesmo SQL com diferentes parâmetros passados em cada vez, pode ajudar a proteger contra injeção de SQL, pode fornecer algumas melhorias de desempenho (driver/protocolo específico, YMMV) e evitar etapas repetidas, como na geração do plano de execução e análise de SQL em o preparar passo acima.
Para alguém escrevendo código-fonte, uma instrução preparada pode ser mais conveniente do que concatenar strings e enviá-las ao servidor de banco de dados.
O
DB.Query()
O método recebe SQL como uma string e zero ou mais argumentos (assim como Exec()
, ou QueryRow()
). Uma string SQL sem argumentos adicionais consultará exatamente o que você escreveu. No entanto, desde uma string SQL com espaços reservados e argumentos adicionais, uma instrução preparada está sendo feita para você nos bastidores. O
DB.Prepare()
explicitamente executa uma instrução preparada, para a qual você passa argumentos, como em:stmt.Exec(...args)
. Há algumas coisas que vale a pena pensar, em termos das diferenças entre os dois e por que usar um ou outro.
Você pode usar
DB.Query()
sem argumentos. Isso pode ser muito eficiente, pois pode ignorar o preparar --> executar --> fechar seqüência pela qual a instrução preparada necessariamente passa. Você também pode usá-lo com argumentos adicionais e espaços reservados na string de consulta, e ele executará uma instrução preparada nos bastidores, como mencionei acima. O problema potencial aqui é que, quando você está fazendo várias consultas, cada uma delas resulta em uma declaração preparada sob o capô. Como há etapas extras envolvidas, isso pode ser bastante ineficiente, pois re-prepara, executa e fecha cada vez que você faz essa consulta.
Com uma instrução preparada explícita, você pode evitar essa ineficiência ao tentar reutilizar o SQL que preparou anteriormente, com argumentos potencialmente diferentes.
Mas isso nem sempre funciona como você poderia esperar... Por causa do pool de conexão subjacente que é gerenciado por db/sql, sua "conexão de banco de dados" é bastante virtual. O
DB.Prepare()
O método preparará a instrução em relação a uma conexão específica e, em seguida, tentará obter essa mesma conexão de volta quando for a hora de executar, mas se essa conexão não estiver disponível, ele simplesmente pegará uma que estiver disponível e preparará novamente e executará com relação a ela. Se você estiver usando a mesma declaração preparada repetidamente, você pode, sem saber, também prepará-la repetidamente. Isso obviamente vem à tona quando você está lidando com tráfego pesado. Então, obviamente, qual você para qual circunstância usar depende do seu caso de uso específico, mas espero que os detalhes acima ajudem a esclarecer o suficiente para que você possa tomar a melhor decisão em cada caso.
Atualizar
Dada a atualização no OP, essencialmente não há diferença quando a consulta precisa ser executada apenas uma vez, pois as consultas com argumentos são feitas como instruções preparadas nos bastidores.
Use os métodos diretos, por exemplo.
DB.Query()
e seus análogos, em vez de usar explicitamente instruções preparadas, pois resultará em um código-fonte um pouco mais simples. Como as instruções preparadas, nesse caso, estão sendo utilizadas por motivos de segurança, pode valer a pena o esforço para lidar com as preocupações de segurança por outros meios e usar consultas de texto simples, pois isso melhorará o desempenho. Quaisquer ganhos, no entanto, podem ser irrelevantes, a menos que haja tráfego suficiente (ou se prevê que o tráfego cresça consideravelmente no futuro) para tornar a carga no servidor mais leve. Novamente, tudo se resume ao caso de uso do mundo real.
Para qualquer pessoa interessada em algumas métricas sobre a diferença entre declarações preparadas e consultas diretas de texto simples, há um bom artigo aqui (que também faz um excelente trabalho ao explicar muito do que foi dito acima).