#绑定参数

如本章首页所述,绑定参数被使用在动态SQL中,其中占位符相当于存储过程/函数中的形参,通过USING语法指定的值或变量相当于存储过程/函数中的实参,区别在于:

  1. 占位符表示的形参不能定义参数类型、缺省值等信息,形参的参数类型依据实参传入值或变量确定。
  2. 实参只能直接输入值或变量,与形参按位置一一对应,与占位符名称无任何关联。
  3. 与存储过程/函数在声明形参时指定IN/OUT/IN OUT类型不同,绑定参数在实参传递变量时才进行指定,且只有动态SQL语句存在返回值时,才可以指定为OUT/IN OUT类型,否则默认为IN类型。
  4. 基于''和NULL无数据类型,实参的值不能为''和NULL。

# 占位符

占位符由:+标识符构成,标识符建议使用数字或字母。

同一SQL语句在实参传递时按照占位符的位置进行参数对应,如果SQL语句绑定不同值时,应该使用不同的占位符名称,否则将编译错误。

示例

--定义一个存储过程,其中a2参数在过程体被赋值输出
CREATE OR REPLACE PROCEDURE ya_block(a1 VARCHAR,a2 IN OUT VARCHAR) IS
no VARCHAR(2);
name VARCHAR(20);
str1 VARCHAR(100) := 'select area_no,area_name from area where area_no in (:a,:b) and rownum=1';
BEGIN
--str1中不存在返回值,不能将绑定变量a1,a2指定OUT/IN OUT类型进行参数传递
EXECUTE IMMEDIATE str1 INTO no,name USING a1,a2;
DBMS_OUTPUT.PUT_LINE('区域号码:'||no||'区域名称:'||name);
a2 := '00';
END;
/
 
DECLARE
a1 VARCHAR(20):='01';
a2 VARCHAR(20):='02';
str2 VARCHAR(200) := 'INSERT INTO area(area_no) VALUES(:a) RETURN TO_NUMBER(area_no), NVL(area_name, ''area''||area_no) INTO :b, :c';
BEGIN
DBMS_OUTPUT.PUT_LINE('before-a1:'||a1||',a2:'||a2);
--ya_block的a2参数存在返回值,可以被定义为OUT/IN OUT类型
EXECUTE IMMEDIATE 'begin ya_block(:b,:c); end;' USING a1,IN OUT a2;
DBMS_OUTPUT.PUT_LINE('plsql.after-a1:'||a1||',a2:'||a2);

--str2中定义了RETURN值,可以将绑定变量a1,a2指定OUT/IN OUT类型进行参数传递
EXECUTE IMMEDIATE str2 USING '09',out a1,out a2;
DBMS_OUTPUT.PUT_LINE('sql.after-a1:'||a1||',a2:'||a2);
END;
/

--result
before-a1:01,a2:02
区域号码:01区域名称:华东
plsql.after-a1:01,a2:00
sql.after-a1:9,a2:area09

# 变量窥视

当使用绑定参数时,YashanDB优化器可以将相似的SQL语句合并成一个执行计划,避免多次的硬解析。

变量窥视是在此功能上的进一步优化,实现了:

  1. 依据实参的数据类型推导SQL语句中占位符的数据类型。
  2. 依据实参传递的绑定变量进行动态窥视,生成最合适的执行计划,而不是只采用依据某一个绑定变量所生成的执行计划。

YashanDB的变量窥视功能不为用户感知,在动态SELECT语句中使用绑定参数时自动调用,提升系统运行效率。

23.1版本开始支持变量窥视之后,一部分绑定变量的场景进行类型推导时会出现与23.1之前的版本不同的现象。

示例

CREATE TABLE t1 (id INT, data CHAR(255));
INSERT INTO t1 VALUES(1, 'test');
COMMIT;
SET serveroutput ON;

DECLARE
   var VARCHAR(100) := 'test';
   count INT;
BEGIN
   SELECT COUNT(*) INTO count FROM t1 WHERE data = var;
   DBMS_OUTPUT.PUT_LINE(count);
END;
/

这个匿名块用例第5行是使用绑定变量的方式将var变量传入SQL语句中执行。

在23.1之前的版本,没有变量窥视,会将待绑定的unknow变量从最近的运算数据类型中推导一个类型。如该例子里,会将var传入之前的unknow数据类型推导为与data相同的类型,即char类型。待var变量传入以后,会将var变量转为char类型再与data比较。此时使用的是char类型与char类型的比较规则,空格是不敏感的,具体可查看字符型,所以用例where条件匹配成功,结果为1。

在23.1及之后的版本,有变量窥视,会将var数据类型的真实数据类型传入,data与var类型比较时,是char类型与varchar类型比较,此时空格是敏感的,具体可查看字符型。所以用例where条件匹配失败,结果为0。

pdf-btn 下载文档
copy-btn 复制链接