您好,我是小DAI,专注于数据库管理员相关的技术问答,请问有什么可以帮您?

表变量类型定义

过程或表函数主体中的表变量类型派生自 SQL 查询或显式声明。如果表变量从 SQL 查询派生其类型,则 SQLScript 编译器通过变量的第一个赋值确定其类型,从而提供很大的灵活性。如果未分配缺省值,则使用空内容初始化显式声明的表变量。

签名

DECLARE  [{, }...] [CONSTANT] {TABLE ()|} [  ]

::= { DEFAULT | '=' } { | | | }

使用 DECLARE 关键字声明本地表变量。对于引用类型,可以使用先前声明的表类型或类型定义 TABLE ()。下一个示例说明了两个变式:

DECLARE temp TABLE (n int);

DECLARE temp MY_TABLE_TYPE;

还可以使用 DEFAULT 关键字或“=”直接为表变量分配默认值。缺省情况下,允许所有 语句,典型的表变量赋值也支持这些语句。

DECLARE temp MY_TABLE_TYPE = UNNEST (:arr) as (i);

DECLARE temp MY_TABLE_TYPE DEFAULT SELECT * FROM TABLE;

也可以使用 CONSTANT 关键字将表变量标记为只读。结果是无法再覆盖变量。请注意,如果使用 CONSTANT 关键字,则表变量应具有缺省值,不能为 NULL

DECLARE temp CONSTANT TABLE(I INT) DEFAULT SELECT * FROM TABLE;

声明表变量的另一种方法是使用 LIKE 关键字。您可以使用持久表、视图或另一个表变量的类型来指定变量类型。

DECLARE  [CONSTANT] LIKE {  | : }. [NOT NULL] [default_value]

DECLARE [CONSTANT] TABLE LIKE { | : } [default_value]

备注使用 LIKE 声明表变量时,被引用表中列的所有属性(如唯一、缺省值等)在声明的变量中都将被忽略,但 not null 属性除外。当使用 LIKE 在过程中声明变量时,该过程将依赖于被引用表。

描述

使用 DECLARE 关键字声明本地表变量。可使用 temp 引用表变量 :temp。有关详细信息,请参阅引用变量。 在同一代码块中的所有其它标量变量和表变量中必须唯一。但是,您可以在不同的代码块中使用与另一个变量名称相同的名称。此外,您只能在其本地范围中引用这些标识符。

CREATE PROCEDURE exampleExplicit (OUT outTab TABLE(n int))

LANGUAGE SQLScript READS SQL DATA AS

BEGIN

DECLARE temp TABLE (n int);

temp = SELECT 1 as n FROM DUMMY ;

BEGIN

DECLARE temp TABLE (n int);

temp = SELECT 2 as n FROM DUMMY ;

outTab = Select * from :temp;

END;

outTab = Select * from :temp;

END;

call exampleExplicit(?);

在每个块中,都有使用相同名称声明的表变量。但是,由于输出参数 的最后赋值只能在同一个块中声明变量 的引用,因此结果如下:

N

1

CREATE PROCEDURE exampleDerived (OUT outTab TABLE(n int))

LANGUAGE SQLScript READS SQL DATA

AS

BEGIN

temp = SELECT 1 as n FROM DUMMY ;

BEGIN

temp = SELECT 2 as n FROM DUMMY ;

outTab = Select * from :temp;

END;

outTab = Select * from :temp;

END;

call exampleDerived (?);

在此代码示例中,没有显式表变量声明已完成,这意味着 变量在所有块中均可见。因此,结果如下:

N

2

对于显式声明的表变量的每个赋值,将根据左侧的显式声明类型检查右侧的派生列名称和类型。

与派生类型相比,另一个区别是在编译期间对表变量的引用将返回警告。

BEGIN

DECLARE a TABLE (i DECIMAL(2,1), j INTEGER);

IF :num = 4

THEN

a = SELECT i, j FROM tab;

END IF;

END;

以上示例返回警告,因为如果 不是 4,则会取消分配表变量 <:num> 。此行为可由配置参数 UNINITIALIZED_TABLE_VARIABLE_USAGE 控制。除了发出警告,它还提供以下选项:

  • 错误:发出错误消息,无法创建程序或功能

  • 静默:不发出消息

    下表显示了差异:

    派生类型显式声明创建新变量第一个 SQL 查询分配tmp = select * from table;块中的表变量声明:DECLARE tmp TABLE(i int);可变范围全局范围,不考虑首次声明的块仅在声明的块中可用。应用变量隐藏。未分配的变量检查编译期间无警告编译期间如果可以参考未分配的表变量,则发出警告。仅当使用表变量时才执行检查。 

    NOT NULL 约束

    您可以在 SQLScript 中使用的表类型中的列上指定 NOT NULL 约束。历史上,语法不允许出现这种情况,并且在 SQLScript 中用作类型时,表和表类型上的现有 NOT NULL 约束将被忽略。现在,如果在表类型的列列表中直接指定 NOT NULL 约束,则会将其考虑在内。缺省情况下,持久表和表类型中的 NOT NULL 约束仍被忽略,以实现向后兼容性,但您可以通过更改配置使其有效,如下所示:

  • 全局:indexserver.ini (sqlscript, not_null_column_mode) = 'ignore' (default), 'ignore_with_warning', 'respect'

  • 会话变量:set '__SQLSCRIPT_NOT_NULL_COLUMN_MODE' = 'ignore' (default), 'ignore_with_warning', 'respect'

    如果两者均已设置,则会话变量优先。将其设置为 'ignore_with_warning' 的效果与 'ignore' 相同,不同之处在于忽略约束时还会收到警告。使用 'respect' ,将考虑表和表类型中的 NOT NULL 约束(包括主键),但这可能会使现有过程失效。考虑以下示例: 示例代码create table mytab (i int primary key);create table mytab2 (i int);create procedure myproc (out ot mytab) as begin ot = select * from mytab2; -- error if not_null_column_mode is set to 'respect'end;