매개변수 마커

매개변수 마커

설명

매개변수 마커(parameter marker)는 SQL 문을 호출하는 API에서 값을 공급받기 위해 사용하는 이름 있는 또는 이름 없는 타입 지정 플레이스홀더 변수예요.

매개변수 마커를 사용하면 제공된 값을 SQL 문과 명확히 분리하기 때문에 코드를 SQL 주입(SQL injection) 공격으로부터 보호할 수 있어요.

같은 SQL 문 안에서 이름 있는 매개변수 마커와 이름 없는 매개변수 마커를 섞어 쓸 수는 없어요.

매개변수 마커는 SQL 문법에서 리터럴 값이 허용되는 어디든 사용할 수 있어요.

테이블 이름이나 컬럼 이름 같은 식별자를 매개변수화하려면 IDENTIFIER을 사용하세요.

매개변수 마커는 다음 방법으로 제공할 수 있어요.

이름 있는 매개변수 마커

이름 있는 매개변수 마커는 타입 지정 플레이스홀더 변수예요. SQL 문을 호출하는 API는 각 매개변수 마커를 값과 연결하기 위해 이름-값 쌍을 제공해야 해요.

문법
` :parameter_name
매개변수
  • named_parameter_name

한정되지 않은 식별자(unqualified identifier) 형태로 제공된 매개변수 마커에 대한 참조.

참고

같은 SQL 문 안에서 같은 매개변수 마커를 여러 번 참조할 수 있어요. 매개변수 마커에 바인딩된 값이 없으면 UNBOUND_SQL_PARAMETER 오류가 발생해요. 제공된 모든 매개변수 마커를 참조할 필요는 없어요.

필수로 앞에 붙는 :(콜론)은 이름 있는 매개변수 마커의 네임스페이스를 컬럼 이름과 SQL 매개변수의 네임스페이스와 구분해 줘요.

예시

다음 예시는 두 개의 매개변수 마커를 정의해요.

  • later: 값 3인 INTERVAL HOUR.
  • x: 값 15.0인 DOUBLE.

x는 여러 번 참조되고, later는 한 번 참조돼요.

  • SQL
> DECLARE stmtStr = 'SELECT current_timestamp() + :later, :x * :x AS square';
> EXECUTE IMMEDIATE stmtStr USING INTERVAL '3' HOURS AS later, 15.0 AS x;
  2024-01-19 16:17:16.692303  225.00
  • Scala
import org.apache.spark.sql.SparkSession

val spark = SparkSession
  .builder()
  .appName("Spark named parameter marker example")
  .getOrCreate()

val argMap = Map("later" -> java.time.Duration.ofHours(3), "x" -> 15.0)
spark.sql(
  sqlText = "SELECT current_timestamp() + :later, :x * :x AS square",
  args = argMap).show()
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+
  • Java
import org.apache.spark.sql.*;
import static java.util.Map.entry;

SparkSession spark = SparkSession
  .builder()
  .appName("Java Spark named parameter marker example")
    .getOrCreate();

Map<String, String> argMap = Map.ofEntries(
  entry("later", java.time.Duration.ofHours(3)),
  entry("x", 15.0)
);

spark.sql(
  sqlText = "SELECT current_timestamp() + :later, :x * :x AS square",
  args = argMap).show();
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+
  • Python
spark.sql("SELECT :x * :y * :z AS volume", args = { "x" : 3, "y" : 4, "z" : 5 }).show()
// +------+
// |volume|
// +------+
// |    60|
// +------+

이름 없는 매개변수 마커

이름 없는 매개변수 마커는 타입 지정 플레이스홀더 변수예요. SQL 문을 호출하는 API는 각 매개변수 마커를 나타나는 순서대로 값과 연결하기 위해 인자 배열을 제공해야 해요.

문법
` ?
매개변수
  • ?: 물음표 형태로 제공된 매개변수 마커에 대한 참조.
참고

이름 없는 매개변수 마커가 나타날 때마다 SQL 문을 호출하는 API가 제공한 값을 순서대로 하나씩 소비해요. 매개변수 마커에 바인딩된 값이 없으면 UNBOUND_SQL_PARAMETER 오류가 발생해요. 제공된 모든 값을 소비할 필요는 없어요.

예시

다음 예시는 세 개의 매개변수 마커를 정의해요.

  • 값 3인 INTERVAL HOUR 하나.
  • 각각 값 15.0인 DOUBLE 두 개.

매개변수가 이름 없으므로 각 제공 값은 많아야 하나의 매개변수에만 소비돼요.

  • SQL
DECLARE stmtStr = 'SELECT current_timestamp() + ?, ? * ? AS square';
EXECUTE IMMEDIATE stmtStr USING INTERVAL '3' HOURS, 15.0, 15.0;
  2024-01-19 16:17:16.692303  225.00
  • Scala
import org.apache.spark.sql.SparkSession

val spark = SparkSession
  .builder()
  .appName("Spark unnamed parameter marker example")
  .getOrCreate()

val argArr = Array(java.time.Duration.ofHours(3), 15.0, 15.0)

spark.sql(
  sqlText = "SELECT current_timestamp() + ?, ? * ? AS square", args = argArr).show()
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+
  • Java
import org.apache.spark.sql.*;

SparkSession spark = SparkSession
  .builder()
  .appName("Java Spark unnamed parameter marker example")
  .getOrCreate();

Object[] argArr = new Object[] { java.time.Duration.ofHours(3), 15.0, 15.0 }

spark.sql(
  sqlText = "SELECT current_timestamp() + ?, ? * ? AS square",
  args = argArr).show();
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+
  • Python
spark.sql("SELECT ? * ? * ? AS volume", args = [ 3, 4, 5 ]).show()
// +------+
// |volume|
// +------+
// |    60|
// +------+

출처: 문서

더 알아보기 (Learn more)