13.5 Prepared Statements위한 SQL 구문
MySQL 5.6은 서버 측의 준비된 명령문을 지원하고 있습니다. 이 지원은 MySQL 4.1에서 사용 가능한 효율적인 클라이언트 / 서버의 바이너리 프로토콜을 이용하고 있습니다. 매개 변수 값을위한 플레이스 홀더를 포함한 준비된 명령문의 사용에는 다음과 같은 장점이 있습니다.
문을 실행할 때마다 분석하기위한 오버 헤드가 줄어 듭니다. 일반적으로 데이터베이스 응용 프로그램 쿼리 및 삭제의 경우
WHERE
업데이트의 경우SET
삽입의 경우VALUES
등의 어구에서 리터럴 또는 변수 값만 변경되지 않은 거의 동일한 양의 문을 처리합니다.SQL 인젝션 공격으로부터의 보호. 매개 변수 값은 이스케이프되지 않은 SQL 인용 부호 및 문장 부호를 사용할 수 있습니다.
응용 프로그램에서 준비된 명령문
서버 측의 준비된 명령문은 C 프로그램을위한 MySQL C API 클라이언트 라이브러리 또는 MySQL Connector / C , Java 프로그램을위한 MySQL Connector / J , .NET 기술을 사용하여 프로그램을위한 MySQL Connector / Net 등 클라이언트 프로그래밍 인터페이스를 통해 사용할 수 있습니다. 예를 들어, C API는 그 준비된 명령문 API를 구성하는 일련의 함수 호출을 제공합니다. 섹션 23.8.8 "C API 준비된 문" 을 참조하십시오. 다른 언어 인터페이스는 C 클라이언트 라이브러리에 링크하여 바이너리 프로토콜을 사용하는 준비된 명령문에 대한 지원을 제공 할 수 있습니다. 그 하나의 예가 PHP 5.0 이상에서 사용할 수있는 mysqli
확장 기능 입니다.
SQL 스크립트에서 준비된 명령문
준비된 명령문에 대체 SQL 인터페이스를 사용할 수 있습니다. 이 인터페이스는 준비된 명령문 API를 통해 바이너리 프로토콜의 사용 정도 효율적이지 않지만, SQL 레벨에서 직접 사용할 수 있기 때문에 프로그래밍이 필요하지 않습니다.
사용할 수있는 프로그래밍 인터페이스가 존재하지 않는 경우에도 사용할 수 있습니다.
mysql 클라이언트 프로그램 등의 서버에 SQL 문을 송신 해 실행시킬 수있는 모든 프로그램에서 사용할 수 있습니다.
MySQL 4.1 이상을 실행하는 서버에 연결되어있는 한, 클라이언트가 이전 버전의 클라이언트 라이브러리를 사용하는 경우에도 사용할 수 있습니다.
준비된 문을위한 SQL 구문은 다음과 같은 상황에서 사용되도록 고려되고 있습니다.
준비된 명령문의 코딩 전에 그것이 응용 프로그램에서 어떻게 작동하는지 테스트하는 경우.
지원하는 프로그래밍 API에 액세스 할 수 없을 때 준비된 명령문을 사용하는 경우.
준비된 명령문에 대한 응용 프로그램의 문제를 대화 형으로 해결하는 경우.
버그 리포트를 제출하도록 준비된 명령문 문제를 재현하는 테스트 케이스를 만드는 경우.
PREPARE, EXECUTE 및 DEALLOCATE PREPARE 문
준비된 문을위한 SQL 구문은 다음 3 개의 SQL 문을 기반으로합니다.
PREPARE
명령문을 실행하기 위해 준비합니다 ( 섹션 13.5.1 "PREPARE 구문" 을 참조하십시오).EXECUTE
는 준비된 명령문을 실행합니다 ( 섹션 13.5.2 "EXECUTE 구문" 을 참조하십시오).DEALLOCATE PREPARE
는 준비된 명령문을 해제합니다 ( 섹션 13.5.3 "DEALLOCATE PREPARE 구문" 을 참조하십시오).
다음의 예는 두 변의 길이가 주어진 삼각형의 빗변을 계산하는 문을 준비하기위한 2 개의 동등한 방법을 보여줍니다.
첫 번째 예는 문자열 리터럴을 사용하여 문 텍스트를 지정하여 준비된 명령문을 작성하는 방법을 보여줍니다.
mysql>PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql>SET @a = 3;
mysql>SET @b = 4;
mysql>EXECUTE stmt1 USING @a, @b;
+------------+ | hypotenuse | +------------+ | 5 | +------------+ mysql>DEALLOCATE PREPARE stmt1;
두 번째 예제도 마찬가지지만 문 텍스트를 사용자 변수로 지정합니다.
mysql>SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql>PREPARE stmt2 FROM @s;
mysql>SET @a = 6;
mysql>SET @b = 8;
mysql>EXECUTE stmt2 USING @a, @b;
+------------+ | hypotenuse | +------------+ | 10 | +------------+ mysql>DEALLOCATE PREPARE stmt2;
다음의 추가 예제는 쿼리를 실행하는 대상 테이블의 이름을 사용자 변수로 저장하여 실행시 테이블을 선택하는 방법을 보여줍니다.
mysql>USE test;
mysql>CREATE TABLE t1 (a INT NOT NULL);
mysql>INSERT INTO t1 VALUES (4), (8), (11), (32), (80);
mysql>SET @table = 't1';
mysql>SET @s = CONCAT('SELECT * FROM ', @table);
mysql>PREPARE stmt3 FROM @s;
mysql>EXECUTE stmt3;
+----+ | a | +----+ | 4 | | 8 | | 11 | | 32 | | 80 | +----+ mysql>DEALLOCATE PREPARE stmt3;
준비된 문은 문이 생성 된 세션에만 적용됩니다. 이전에 생성 된 준비된 명령문을 해제하지 않고 세션을 종료했을 경우, 그 문은 서버에서 자동으로 해제됩니다.
준비된 명령문은 또한 세션에 대해 글로벌이기도합니다. 스토어드 루틴 내에서 준비된 명령문을 작성했을 경우, 그 문은 스토어드 루틴이 종료 된 후에도 해제되지 않습니다.
동시에 생성되는 준비된 명령문이 너무 많아 않도록하려면 max_prepared_stmt_count
시스템 변수를 설정합니다. 준비된 명령문의 사용을 방지하려면이 값을 0으로 설정합니다.
준비된 명령문 내에서 허용되는 SQL 구문
다음 SQL 문은 준비된 명령문으로 사용할 수 있습니다.
ALTER TABLE ALTER USER (as of MySQL 5.6.8) ANALYZE TABLE CACHE INDEX CALL CHANGE MASTER CHECKSUM {TABLE | TABLES} COMMIT {CREATE | RENAME | DROP} DATABASE {CREATE | DROP} INDEX {CREATE | RENAME | DROP} TABLE {CREATE | RENAME | DROP} USER {CREATE | DROP} VIEW DELETE DO FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES | LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES} GRANT INSERT INSTALL PLUGIN KILL LOAD INDEX INTO CACHE OPTIMIZE TABLE REPAIR TABLE REPLACE RESET {MASTER | SLAVE | QUERY CACHE} REVOKE SELECT SET SHOW {AUTHORS | CONTRIBUTORS | WARNINGS | ERRORS} SHOW BINLOG EVENTS SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW} SHOW {MASTER | BINARY} LOGS SHOW {MASTER | SLAVE} STATUS SLAVE {START | STOP} TRUNCATE TABLE UNINSTALL PLUGIN UPDATE
기타 문의는 MySQL 5.6에서 지원되지 않습니다.
일반적으로 SQL 준비된 명령문에서 허용되지 않은 문은 저장 프로그램에서도 허용되지 않습니다. 예외는 섹션 D.1 "저장 프로그램 제한 사항" 에 나와 있습니다.
준비된 문에서 참조되는 테이블이나 뷰의 메타 데이터 변경이 감지되고 그것이 다음 실행 때 문이 자동으로 다시 준비됩니다. 자세한 내용은 섹션 8.9.4 "준비된 문 및 저장 프로그램 캐시" 를 참조하십시오.
준비된 문을 사용하는 경우, LIMIT
절 인수에 자리 표시자를 사용할 수 있습니다. 섹션 13.2.9 "SELECT 구문" 을 참조하십시오.
PREPARE
및 EXECUTE
와 함께 사용되는 준비된 CALL
문은 OUT
및 INOUT
매개 변수에 대한 자리 표시 자에 대한 지원이 MySQL 5.6에서 사용할 수 있습니다. 예 및 이전 버전에서의 해결 방법에 대해서는 섹션 13.2.1 "CALL 구문" 을 참조하십시오. IN
매개 변수는 버전에 관계없이 자리 표시자를 사용할 수 있습니다.
준비된 문을위한 SQL 문법은 중첩 된 방법으로 사용할 수 없습니다. 즉, PREPARE
에 전달되는 문 자체를 PREPARE
, EXECUTE
또는 DEALLOCATE PREPARE
문에 할 수 없습니다.
준비된 문을위한 SQL 문법은 준비된 문 API 호출의 사용과는 다릅니다. 예를 들어, mysql_stmt_prepare()
C API 함수를 사용하여 PREPARE
, EXECUTE
또는 DEALLOCATE PREPARE
문을 준비 할 수 없습니다.
준비된 문을위한 SQL 구문은 저장 프로 시저에서 사용할 수 있지만, 스토어드 함수 또는 트리거에서 사용할 수 없습니다. 그러나 PREPARE
와 EXECUTE
준비 및 실행되는 동적 명령문은 커서를 사용할 수 없습니다. 커서의 문은 커서 작성시 체크되기 때문에 그 문을 동적으로 할 수 없습니다.
준비된 문을위한 SQL 구문은 멀티 문 (즉, " ;
"문자로 구분 된 하나의 문자열의 여러 문)을 지원하지 않습니다.
준비된 문은 섹션 8.9.3.1 "쿼리 캐시 동작" 에 설명하는 상황에서 쿼리 캐시를 사용합니다.
CALL
SQL 문을 사용하여 준비된 명령문이 포함 된 저장 프로 시저를 실행하는 C 프로그램을 작성하려면 CLIENT_MULTI_RESULTS
플래그가 활성화되어 있어야합니다. 이것은 각 CALL
에 의해 프로 시저 내에서 실행되는 문에 의해 반환 될 수있는 결과 세트 이외에 호출 상태를 나타 내기위한 결과가되기 때문입니다.
CLIENT_MULTI_RESULTS
는 mysql_real_connect()
를 호출 할 때 CLIENT_MULTI_RESULTS
플래그 자체를 전달하여 명시 적으로 또는 CLIENT_MULTI_STATEMENTS
을 전달하여 암시 적으로 사용하는 (따라서 CLIENT_MULTI_RESULTS
도 적용됩니다) 수 있습니다. 자세한 내용은 섹션 13.2.1 "CALL 구문" 을 참조하십시오.