프리페어드 스테이트먼트

**프리페어드 스테이트먼트**(prepared statement), **파라미터라이즈드 스테이트먼트**(parameterized statement)는 데이터베이스 관리 시스템(DBMS)에서 동일하거나 비슷한 데이터베이스 문을 높은 효율성으로 반복적으로 실행하기 위해 사용되는 기능이다. 일반적으로 쿼리나 업데이트와 같은 SQL 문과 함께 사용되는 프리페어드 스테이트먼트는 템플릿의 형태를 취하며, 그 템플릿 안으로 특정한 상수값이 매 실행 때마다 대체된다. 프리페어드 스테이트먼트의 일반적인 워크플로는 다음과 같다: # **준비**(Prepare): 먼저 애플리케이션은 문의 틀을 만들고 이를 DBMS로 보낸다. 특정값은 지정하지 않은 채로 남겨지며 이들은 "변수", "플레이스홀더", "바인드값"으로 부른다. (아래의 "?" 레이블 참고): #: INSERT INTO products (name, price) VALUES (?, ?); # 그 다음, DBMS는 문의 틀을 컴파일하며(최적화 및 변환) 아직 실행하지 않고 결과만 저장한다. # **실행**(Execute): 나중에 애플리케이션이 문 틀의 변수에 값(바인드)을 지정하면 DBMS는 (결과를 반환할 수도 있는) 문을 실행한다. 애플리케이션은 여러 값으로 원하는 횟수만큼 문을 실행할 수 있다. 위의 예에서 첫 번째 변수로 "bike"로, 두 번째 변수로 "10900"을 지정한다.
# 소프트웨어 지원
MySQL,url-status= dead 오라클,accessdate= 25 September 2011 DB2,accessdate= 25 September 2011url=http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fsqlp%2Frbafyplepexc.htm 마이크로소프트 SQL 서버accessdate= 25 September 2011, PostgreSQL을 포함한 주요 DBMS들은 프리페어드 스테이트먼트를 폭넓게 지원한다.accessdate= 27 February 2016
# 예

## 자바 JDBC
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Main { public static void main(String[] args) throws SQLException { MysqlDataSource ds = new MysqlDataSource(); ds.setDatabaseName("mysql"); ds.setUser("root"); try (Connection conn = ds.getConnection()) { try (Statement stmt = conn.createStatement()) { stmt.executeUpdate("CREATE TABLE IF NOT EXISTS products (name VARCHAR(40), price INT)"); } try (PreparedStatement stmt = conn.prepareStatement("INSERT INTO products VALUES (?, ?)")) { stmt.setString(1, "bike"); stmt.setInt(2, 10900); stmt.executeUpdate(); stmt.setString(1, "shoes"); stmt.setInt(2, 7400); stmt.executeUpdate(); stmt.setString(1, "phone"); stmt.setInt(2, 29500); stmt.executeUpdate(); } try (PreparedStatement stmt = conn.prepareStatement("SELECT * FROM products WHERE name = ?")) { stmt.setString(1, "shoes"); ResultSet rs = stmt.executeQuery(); rs.next(); System.out.println(rs.getInt(2)); } } } }
## PHP PDO
exec("CREATE TABLE IF NOT EXISTS products (name VARCHAR(40), price INT)"); $stmt = $conn->prepare("INSERT INTO products VALUES (?, ?)"); $params = array(array("bike", 10900), array("shoes", 7400), array("phone", 29500)); foreach ($params as $param) $stmt->execute($param); $stmt = $conn->prepare("SELECT * FROM products WHERE name = ?"); $params = array("shoes"); $stmt->execute($params); echo $stmt->fetch()[1]; } finally { if ($stmt !== null) $stmt->closeCursor(); } ?>
## 펄 DBI
my $stmt = $db->prepare("SELECT * FROM users WHERE USERNAME = ? AND PASSWORD = ?"); $stmt->execute($username, $password);
## C# ADO.NET
using (SqlCommand command = connection.CreateCommand()) { command.CommandText = "SELECT * FROM users WHERE USERNAME = @username AND ROOM = @room"; command.Parameters.AddWithValue("@username", username); command.Parameters.AddWithValue("@room", room); using (SqlDataReader dataReader = command.ExecuteReader()) { // ... } }
## 파이썬 DB-API
import mysql.connector conn = None cursor = None try: conn = mysql.connector.connect(database="mysql", user="root") cursor = conn.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS products (name VARCHAR(40), price INT)") params = [("bike", 10900), ("shoes", 7400), ("phone", 29500)] cursor.executemany("INSERT INTO products VALUES (%s, %s)", params) params = ("shoes",) cursor.execute("SELECT * FROM products WHERE name = %s", params) print(cursor.fetchall()[0][1]) finally: if cursor is not None: cursor.close() if conn is not None: conn.close()
## 매직 다이렉트 SQL
Virtual username Alpha 20 init: 'sister' Virtual password Alpha 20 init: 'yellow' SQL Command: SELECT * FROM users WHERE USERNAME=:1 AND PASSWORD=:2 Input Arguments: 1: username 2: password