Suporte ao software
Os principais DBMSs, incluindo SQLite, MySQL, Oracle, IBM DB2, Microsoft SQL Server e PostgreSQL Suporte, instruções preparadas. As declarações preparadas são normalmente executadas através de um protocolo binário não-SQL para eficiência e proteção contra injeção de SQL, mas com alguns DBMSs, como declarações preparadas para MySQL, também estão disponíveis usando uma sintaxe SQL para fins de depuração.
Várias linguagens de programação suportam declarações preparadas em suas bibliotecas padrão e as imitam no lado do cliente, mesmo que o DBMS subjacente não as suportasse, incluindo o JDBC da Java, o DBI da Perl, o PDO do PHP e o DB-API do Python. A emulação do lado do cliente pode ser mais rápida para consultas que são executadas apenas uma vez, reduzindo o número de viagens redondas ao servidor, mas geralmente é mais lento para consultas executadas muitas vezes. Resiste a ataques de injeção de SQL de maneira igualmente eficaz.
Muitos tipos de ataques de injeção de SQL podem ser eliminados por desativar literais, exigindo efetivamente o uso de declarações preparadas; A partir de 2007 [atualização], apenas o H2 suporta esse recurso.
Exemplos
Java JDBC
Este exemplo usa Java e JDBC:
import com.mysql.jdbc.jdbc2.optional.mysqldataSource; importar java.sql.connection; importar java.sql.driverManager; importar java.sql.PreparedStatement; import java.ql.ResultSets; .sql.statement; public class Main {public static void main (string [] args) lança sqLexception {mysqldatasource ds = new mysqldatasource (); ds.setDatabasename ("MySQL"); ds.setUser ("raiz"); tente (conexão conn = ds.getConnection ()) {try (instrução stmt = conn.createstatement ()) {stmt.executeUpdate ("Criar tabela se não existe produtos (nome varchar (40), preço int)"); } tente (preparado estatamento stmt = conn.preparestatement ("inserir nos valores dos produtos (?,?)")) {stmt.setstring (1, "bicicleta"); stmt.setInt (2, 10900); stmt.executeUpdate (); STMT.SETSTRING (1, "Sapatos"); stmt.setInt (2, 7400); stmt.executeUpdate (); stmt.SetString (1, "telefone"); stmt.setInt (2, 29500); stmt.executeUpdate (); } tente (preparado estatamento stmt = conn.preparestatement ("selecione * de produtos onde nome =?")) {stmt.setstring (1, "sapatos"); ResultSet rs = stmt.executeQuery (); rs.Next (); System.out.println (rs.getInt (2)); }}}}
O Java PreparedStatement fornece "setters" (setInt (int), SetString (String), SetDouble (duplo), etc.) para todos os principais tipos de dados internos.
PHP PDO
Este exemplo usa PHP e PDO:
tente {// conecte -se a um banco de dados chamado "mysql", com a senha "root" $ conexão = new PDO ('mysql: dbname = mysql', 'root'); // Execute uma solicitação na conexão, que criará // uma tabela "Produtos" com duas colunas, "nome" e "Price" $ conexão-> Exec ('Criar tabela se não existe produtos (nome Varchar (40), preço int) '); // Prepare uma consulta para inserir vários produtos na tabela $ declaração = $ conexão-> preparar ('inserir nos valores dos produtos (?,?)'); $ produtos = [['bicicleta', 10900], ['sapatos', 7400], ['telefone', 29500],]; // itera através dos produtos na matriz "Produtos" e // Execute a declaração preparada para cada produto foreach ($ produtos como $ produto) {$ declaração-> Execute ($ produto); } // Prepare uma nova instrução com um parâmetro nomeado $ declaração = $ Connection-> Prepare ('Selecione * FROM PRODUTOS WHERE Nome =: Nome'); $ declaração-> execute ([': name' => 'Shoes',]); // Use a destruição de matrizes para atribuir o nome do produto e seu preço // às variáveis correspondentes [$ Product, $ price] = $ declaração-> fetch (); // Exibe o resultado para o usuário ecoar "O preço do produto {$ Product} é \ $ {$ price}."; // Fechar o cursor SO `fetch` pode eventualmente ser usado novamente $ Declaração-> ClosCursor ();} Catch (\ Exception $ e) {echo 'Ocorreu um erro:'. $ e-> getMessage ();}
Perl DBI
Este exemplo usa Perl e DBI:
#!/usr/bin/perl -wuse rigoroso; use dbi; meu ($ db_name, $ db_user, $ db_password) = ('my_database', 'moi', 'passw0rd'); my $ dbh = dbi-> conectar ( "DBI: mysql: database = $ db_name", $ db_user, $ db_password, {raiseerror => 1, autocomit => 1}) ou die "erro (main: dbi-> conectar) enquanto se conecta ao banco de dados $ db_name:" $ Dbi :: errstr. "\ n"; $ dbh-> do ('Criar tabela se não existe produtos (nome varchar (40), price int)'); meu $ sth = $ dbh-> preparar ('inserir nos valores dos produtos (?,? ) '); $ STH-> Execute (@$ _) foreach [' Bike ', 10900], [' Shoes ', 7400], [' telefone ', 29500]; $ sth = $ dbh-> preparar ("Selecionar * De produtos onde o nome =? "); $ Sth-> Execute ('sapatos'); imprimir" $$ _ [1] \ n "foreach $ sth-> fetchrow_arrayref; $ sth-> acabamento; $ dbh-> desconectando ;
C# Ado.net
Este exemplo usa C# e Ado.net:
usa (sqlCommand command = Connection.createCommand ()) {command.CommandText = "Selecione * dos usuários onde o nome de usuário = @username e sala = @room"; command.parameters.addwithValue ("@userName", nome de usuário); command.parameters.addwithValue ("@Room", quarto); usando (sqldatareader dataReader = command.exectereader ()) {// ...}}
O ADO.NET SQLCommand aceitará qualquer tipo para o parâmetro de valor do AddWithValue, e a conversão do tipo ocorre automaticamente. Observe o uso de "parâmetros nomeados" (ou seja, "@username") em vez de "?" - Isso permite que você use um parâmetro várias vezes e em qualquer ordem arbitrária no texto do comando de consulta.
No entanto, o método AddWithValue não deve ser usado com tipos de dados de comprimento variável, como varchar e nvarchar. Isso ocorre porque o .NET assume que o comprimento do parâmetro é o comprimento do valor fornecido, em vez de obter o comprimento real do banco de dados por meio de reflexão. A conseqüência disso é que um plano de consulta diferente é compilado e armazenado para cada comprimento diferente. Em geral, o número máximo de planos "duplicados" é o produto dos comprimentos das colunas de comprimento variável, conforme especificado no banco de dados. Por esse motivo, é importante usar o método Adicionar padrão para colunas de comprimento variável:
Command.parameters.add (paramname, varchar, paramLength) .Value = paramvalue, onde o paramLength é o comprimento, conforme especificado no banco de dados.
Como o método Adicionar padrão precisa ser usado para tipos de dados de comprimento variável, é um bom hábito usá -lo para todos os tipos de parâmetros.
Python DB-API
Este exemplo usa Python e DB-API:
importar mysql.connectorwith mysql.connector.connect (database = "mysql", user = "root") como conn: com Conn.cursor (preparado = true) como cursor: cursor.execute ("Criar tabela se não existir (nome de nome (nome Varchar (40), Price int) ") params = [(" Bike ", 10900), (" Shoes ", 7400), (" Telefone ", 29500)] cursor.executemany (" Inserir em valores de produtos (%s, %s) ", params) params = (" sapatos ",) cursor.execute (" selecione * de produtos onde nome = %s ", params) print (cursor.fetchall () [0] [1])
Magic Direct SQL
Este exemplo usa SQL direto da linguagem da quarta geração, como Edeveloper, Unipaas e Magic XPA da Magic Software Enterprises
Virtual username Alpha 20 init: 'sister'Virtual password Alpha 20 init: 'yellow'SQL Command: SELECT * FROM users WHERE USERNAME=:1 AND PASSWORD=:2Input Arguments: 1: username2: password
PureBasic
PureBasic (já que V5.40 LTS) pode gerenciar 7 tipos de link com os seguintes comandos
SetDatabaseBlob, SetDatabaseDouble, SetDatabaseFloat, SetDatabaseLong, SetDatabaseNull, SetDatabaseQuad, SetDatabaseString
Existem 2 métodos diferentes, dependendo do tipo de banco de dados
Para SQLite, ODBC, MARIADB/MYSQL Use :?
SetDatABASEstring (#Database, 0, "Test") se DatabaseQuery (#Database, "Selecione * do funcionário onde id =?"); ... Fim se
Para uso do PostgreSQL: $ 1, $ 2, $ 3, ...
SetDatAbaseString (#Database, 0, "Smith"); -> $ 1 setDatabaseString (#Database, 1, "sim"); -> $ 2 setDatabaseLong (#Database, 2, 50); -> $ 3 se DatabaseQuery (#DATABASE, "SELECT * FROM FUNCIONAL WHERE ID = $ 1 e ativo = $ 2 e anos> $ 3"); ... Fim se