1. 程式人生 > 實用技巧 >HANA SQL Script學習(3):Logic Container

HANA SQL Script學習(3):Logic Container

3Logic Container

/*

2.Logic Container

邏輯程式碼塊分類:1.Procedure;2.User-Defined Function

User-Defined Function分類:Scalar User-Defined Function and Table User-Defined Function.

3.1 Procedure

--2.1建立procedure

語法:

CREATE [OR REPLACE] PROCEDURE <proc_name>

[(<parameter_clause>)]

[LANGUAGE <lang>]

[SQL SECURITY <mode>]

[DEFAULT SCHEMA <default_schema_name>]

[READS SQL DATA ]

[WITH ENCRYPTION]

[AUTOCOMMIT DDL ON|OFF]

AS

BEGIN

[SEQUENTIAL EXECUTION]

<procedure_body>

END

<proc_name> ::= [<schema_name>.]<identifier>

<parameter_clause> ::= <parameter> [{, <parameter>}...]

<param_inout> ::= IN | OUT | INOUT

預設IN

<param_type> ::= <sql_type> [ARRAY] | <table_type> | <table_type_definition> | <any_table_type>

<sql_type> ::= DATE | TIME| TIMESTAMP | SECONDDATE | TINYINT | SMALLINT | INTEGER | BIGINT

|DECIMAL | SMALLDECIMAL | REAL | DOUBLE

| VARCHAR | NVARCHAR | ALPHANUM | VARBINARY | CLOB | NCLOB | BLOB | ST_GEOMETRY | ARRAY

<table_type_definition> ::= TABLE (<column_list_definition>)

<column_list_definition> ::= <column_elem>[{, <column_elem>}...]

<column_elem> ::= <column_name> <data_type>

LANGUAGE <lang>

<lang> ::= SQLSCRIPT | R

指定語言,預設SQLSCRIPT

SQL SECURITY <mode>

<mode> ::= DEFINER | INVOKER

指定安全模式,預設DEFINER.DEFINER:以procedure建立者許可權執行;INVOKER:以procedure執行時的許可權執行;

DEFAULT SCHEMA <default_schema_name>

<default_schema_name> ::= <unicode_name>

預設當前schema

READS SQL DATA

只讀,沒有DDL(資料庫表檢視的增刪改)和DML(資料記錄的增刪改)語句

AUTOCOMMIT DDL ON|OFF

預設:OFF,某些語句必須ON才能使用,例如:IMPORT

SEQUENTIAL EXECUTION

強制順序執行,不會並行

<procedure_body> ::= [<proc_decl_list>][<proc_handler_list>] <proc_stmt_list>

<proc_decl_list> ::= <proc_decl> [{, <proc_decl>}…]

<proc_decl> ::= DECLARE {<proc_variable>|<proc_table_variable>|<proc_cursor>| <proc_condition>} ;

<proc_cursor> ::= CURSOR <cursor_name> [ ( proc_cursor_param_list ) ] FOR <subquery> ;

<cursor_name>::= <identifier>

<proc_cursor_param_list> ::= <proc_cursor_param> [{, <proc_cursor_param>}...]

<proc_cursor_param>::= <param_name> <datatype>

<proc_variable>::= <variable_name_list> [CONSTANT] {<sql_type>| <array_datatype>}[NOT NULL][<proc_default>]

<array_datatype>::= <sql_type> ARRAY [ = <array_constructor> ]

<array_constructor>::= ARRAY (<expression> [ { , <expression> }...] )

<proc_default>::= (DEFAULT | '=' ) <value>|<expression>

<value>::= An element of the type specified by <type> or an expression

<proc_table_variable> ::= <variable_name_list> {<table_type_definition>| <table_type>}

<variable_name_list>::= <variable_name>[{, <variable_name}...]

<column_list_elements>::= (<column_definition>[{,<column_definition>}...])

<proc_condition>::= <variable_name> CONDITION | <variable_name> CONDITION FOR <sql_error_code>

<variable_name>::= <identifier>

<proc_handler_list> ::= <proc_handler> [{, <proc_handler>}...]

<proc_handler>::= DECLARE EXIT HANDLER FOR <proc_condition_value_list> <proc_stmt> ;

<proc_condition_value_list> ::= <proc_condition_value> {,<proc_condition_value>}...]

<proc_condition_value> ::= SQLEXCEPTION | <sql_error_code> | <condition_name>

<proc_stmt_list> ::= {<proc_stmt>}...

<proc_stmt> ::= <proc_block> | <proc_assign> | <proc_single_assign> | <proc_multi_assign> | <proc_if>

| <proc_loop> | <proc_while> | <proc_for> | <proc_foreach> | <proc_exit>

| <proc_continue>| <proc_signal> | <proc_resignal> | <proc_sql> | <proc_open>

| <proc_fetch> | <proc_close> | <proc_call> | <proc_exec> | <proc_return>

| <proc_insert> | <proc_update> | <proc_delete>

<proc_insert> ::= :<table_variable>.INSERT((<value_1>,…, <value_n>), <index>)

<proc_update> ::= :<table_variable>.UPDATE((<value_1>,…, <value_n>), <index>)

<proc_update> ::= <table_variable>[<index>] = (<value_1>,…, <value_n>)

<proc_delete> ::= :<table_variable>.DELETE(<index>)

<proc_delete> ::= :<table_variable>.DELETE(<from_index>..<to_index>)

<proc_block> ::=

BEGIN <proc_block_option>

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

END ;

<proc_block_option> ::=

[SEQUENTIAL EXECUTION ]

| [AUTONOMOUS TRANSACTION]

| [PARALLEL EXECUTION]

<proc_assign> ::= <variable_name> = { <expression> | <array_function> } ;

| <variable_name> '[' <expression> ']' = <expression> ;

<array_function> = ARRAY_AGG ( :<table_variable>.<column_name> [ ORDER BY <sort_spec_list> ] )

| CARDINALITY ( :<array_variable_name>)

| TRIM_ARRAY ( :<array_variable_name> , <array_variable_name>)

| ARRAY ( <array_variable_name_list> )

<table_variable> ::= <identifier>

<column_name> ::= <identifier>

<array_variable_name> ::= <identifier>

<proc_multi_assign> ::= (<var_name_list>) = <function_expression>

<proc_single_assign> ::= <variable_name> = <subquery>

| <variable_name> = <proc_ce_call>

| <variable_name> = <proc_apply_filter>

| <variable_name> = <unnest_function>

| <variable_name> = <map_merge_op>

<map_merge_op> ::= MAP_MERGE(<table_or_table_variable>, <mapper_identifier>(<table_or_table_variable>.<column_name> [ {, <table_or_table_variable>.<column_name>} … ] [, <param_list>])

<table_or_table_variable> ::= <table_variable_name> | <identifier>

<table_variable_name> ::= <identifier>

<mapper_identifier> ::= <identifier>

<column_name> ::= <identifier>

<param_list> ::= <param> [{, <param>} …]

<paramter> = <table_or_table_variable> | <string_literal> | <numeric_literal> | <identifier>

<proc_ce_call> ::= TRACE ( <variable_name> ) ;

| CE_LEFT_OUTER_JOIN ( <table_variable> , <table_variable> , '[' <expr_alias_comma_list> ']' [ <expr_alias_vector>] ) ;

| CE_RIGHT_OUTER_JOIN ( <table_variable> , <table_variable> , '[' <expr_alias_comma_list> ']' [ <expr_alias_vector>] ) ;

| CE_FULL_OUTER_JOIN ( <table_variable> , <table_variable> , '[' <expr_alias_comma_list> ']' [ <expr_alias_vector>] );

| CE_JOIN ( <table_variable> , <table_variable> , '[' <expr_alias_comma_list> ']' [<expr_alias_vector>] ) ;

| CE_UNION_ALL ( <table_variable> , <table_variable> ) ;

| CE_COLUMN_TABLE ( <table_name> [ <expr_alias_vector>] ) ;

| CE_JOIN_VIEW ( <table_name> [ <expr_alias_vector>] ) ;

| CE_CALC_VIEW ( <table_name> [ <expr_alias_vector>] ) ;

| CE_OLAP_VIEW ( <table_name> [ <expr_alias_vector>] ) ;

| CE_PROJECTION ( <table_variable> , '[' <expr_alias_comma_list> ']' <opt_str_const> ) ;

| CE_PROJECTION ( <table_variable> <opt_str_const> ) ;

| CE_AGGREGATION ( <table_variable> , '[' <agg_alias_comma_list> ']' [ <expr_alias_vector>] );

| CE_CONVERSION ( <table_variable> , '[' <proc_key_value_pair_comma_list> ']' [ <expr_alias_vector>] ) ;

| CE_VERTICAL_UNION ( <table_variable> , '[' <expr_alias_comma_list> ']' <vertical_union_param_pair_list> ) ;

| CE_COMM2R ( <table_variable> , <int_const> , <str_const> , <int_const> , <int_const> , <str_const> ) ;

<table_name> ::= [<schema_name>.]<identifier>

<proc_apply_filter> ::= APPLY_FILTER ( {<table_name> | :<table_variable>}, <variable_name> ) ;

<unnest_function> ::= UNNEST ( <variable_name_list> ) [ WITH ORDINALITY ] [<as_col_names>] ;

<variable_name_list> ::= :<variable_name> [{, :<variable_name>}...]

WITH ORDINALTIY:新增ordinal列

<as_col_names> ::= AS [table_name] ( <column_name_list> )

<column_name_list> ::= <column_name>[{, <column_name>}...] <column_name> ::= <identifier>

返回表名,列名

if 語句

<proc_if> ::= IF <condition> THEN

[SEQUENTIAL EXECUTION][<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

[<proc_elsif_list>]

[<proc_else>]

END IF ;

<proc_elsif_list> ::= ELSEIF <condition> THEN

[SEQUENTIAL EXECUTION]

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

<proc_else> ::= ELSE

[SEQUENTIAL EXECUTION]

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

loop 語句

<proc_loop> ::=

LOOP

[SEQUENTIAL EXECUTION]

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

END LOOP ;

while 語句

<proc_while> ::=

WHILE <condition> DO

[SEQUENTIAL EXECUTION]

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

END WHILE ;

for 語句

<proc_for> ::=

FOR <column_name> IN [ REVERSE ] <expression> [...] <expression> DO

[SEQUENTIAL EXECUTION]

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

END FOR ;

foreach 語句:

<proc_foreach> ::=

FOR <column_name> AS <column_name> [<open_param_list>] DO

[SEQUENTIAL EXECUTION]

[<proc_decl_list>]

[<proc_handler_list>]

<proc_stmt_list>

END FOR ;

<open_param_list> ::= ( <expression> [ { , <expression> }...] )

跳出迴圈語句:

<proc_exit> ::= BREAK ;

跳過本次迴圈,繼續下次:

<proc_continue> ::= CONTINUE ;

定義signal,顯式丟擲異常

<proc_signal> ::= SIGNAL <signal_value> [<set_signal_info>] ;

定義resignal,捕獲異常

<proc_resignal> ::= RESIGNAL [<signal_value>] [<set_signal_info>] ;

<signal_value> ::= <signal_name> | <sql_error_code>

<signal_name> ::= <identifier>

<sql_error_code> ::= <unsigned_integer>

<set_signal_info> ::= SET MESSAGE_TEXT = '<message_string>'

<message_string> ::= <any_character>

sql語句

<proc_sql> ::= <subquery> | <select_into_stmt> | <insert_stmt>

| <delete_stmt> | <update_stmt> | <replace_stmt>

| <call_stmt> | <create_table> | <drop_table>

| <truncate_statement>

查詢語句

<select_into_stmt> ::= SELECT <select_list> INTO <var_name_list> [DEFAULT <scalar_expr_list>]

<from_clause >

[<where_clause>]

[<group_by_clause>]

[<having_clause>]

[{<set_operator> <subquery>, ... }]

[<order_by_clause>]

[<limit>] ;

<var_name_list> ::= <var_name>[{, <var_name>}...]

<var_name> ::= <identifier>

Cursor操作

<proc_open> ::= OPEN <cursor_name> [ <open_param_list>] ;

<proc_fetch> ::= FETCH <cursor_name> INTO <column_name_list> ;

<proc_close> ::= CLOSE <cursor_name> ;

呼叫procedure

<proc_call> ::= CALL <proc_name> (<param_list>) ;

執行呼叫動態SQL

<proc_exec> ::= {EXEC | EXECUTE IMMEDIATE} <proc_expr> ;

返回procedure值

<proc_return> ::= RETURN [<proc_expr>] ;

/*
例項1:建立procedure,顯示資訊
//建立table:message_box */ CREATE TABLE test_message_box (p_msg VARCHAR(200), tstamp TIMESTAMP); CREATE PROCEDURE insert_msg_proc (p_msg VARCHAR(200)) LANGUAGE SQLSCRIPT AS BEGIN INSERT INTO test_message_box VALUES (:p_msg, CURRENT_TIMESTAMP); END;
/*
例項:2
//建立cursor,呼叫cursor。
*/
CREATE PROCEDURE test_proc1
      LANGUAGE SQLSCRIPT AS
BEGIN  
       DECLARE v_id STRING; 
       DECLARE v_name STRING;  
       DECLARE v_price DECIMAL(10,2);  
       DECLARE v_msg VARCHAR(200);  

       DECLARE CURSOR c_cursor1 (p_price DECIMAL(10,2)) FOR    
       SELECT "Product_ID","Product_Name","Price" FROM "MyProducts"   
              WHERE "Price" > :p_price
              ORDER BY "Product_ID" ASC;  
       OPEN c_cursor1(40);  
       FETCH c_cursor1 INTO v_id, v_name, v_price;
       v_msg = :v_name || ' (id ' || :v_id || ') sell ' || :v_price || ' $.';  
       CALL insert_msg_proc(:v_msg);  
       CLOSE c_cursor1;
END;

/*

2.1.2 呼叫procedure

CALL <proc_name> (<param_list>) [WITH OVERVIEW]

<proc_name> ::= [<schema_name>.]<identifier>

<param_list> ::= <proc_param>[{, <proc_param>}...]

<proc_param> ::= <identifier> | <string_literal> | <unsigned_integer> | <signed_integer>| <signed_numeric_literal> | <unsigned_numeric_literal> | <expression>

[WITH OVERVIEW]

當返回值為表資料集時,將資料插入對應OUT引數表;如果OUT ?,臨時表儲存返回資料

procedure內部呼叫procedure

CALL <proc_name > (<param_list>)

<param_list> ::= <param>[{, <param>}...]

<param>::= <in_table_param> | <in_scalar_param> |<out_scalar_param> | <out_table_param>| <inout_scalar_param>

<in_table_param> ::= <in_param>

<in_param> ::= :<identifier>

<in_scalar_param> ::= <in_param>|<scalar_value>|<expression>

<out_param> ::= <identifier>

<out_scalar_param> ::= <out_ param>

<out_table_param> ::= <out_ param>

<inout_scalar_param> ::= <out_ param>

建立procedure時,設定預設值

IN <param_name> (<sql_type>|<table_type>|<table_type_definition>) DEFAULT (<value>|<table_name>)

當引數型別為table時,可以設定為empty

(IN|OUT) <param_name> (<table_type>|<table_type_definition>) DEFAULT EMPTY

*/

CALL test_proc1();

/*建立test procedure 表*/
CREATE TABLE TEST_PROC( id INT,name VARCHAR(10),val DECIMAL(10,2) );
CREATE TABLE TEST_PROC_TEMP( id INT,name VARCHAR(10),val DECIMAL(10,2) );
INSERT INTO TEST_PROC VALUES( 1, 'test1', 4.32 );
INSERT INTO TEST_PROC VALUES( 2, 'test2', 1.43 );
INSERT INTO TEST_PROC VALUES( 3, 'test3', 20.63 );

/*建立table型別*/
CREATE TYPE TYPETABLE AS TABLE ( id INTEGER,name VARCHAR(10),val DECIMAL(10,2) );

/*建立procedure2*/
CREATE PROCEDURE test_proc2(IN id INTEGER,OUT resTab TYPETABLE)
       LANGUAGE SQLSCRIPT AS
BEGIN
       resTab = SELECT * FROM TEST_PROC WHERE id = :id;
END;

/*呼叫procedure*/
CALL test_proc2(1,?);
CALL test_proc2(2,?) WITH OVERVIEW;
CALL test_proc2(2+1,?);
/*使用物理表作為引數時,必須使用with overview,會將返回結果寫入物理表中*/
CALL test_proc2(1,test_proc_temp) WITH OVERVIEW;
/*直接通過引數名呼叫procedure,這樣可以忽略引數順序*/
CALL test_proc2(resTab=>?,id=>2);

/*建立procedure3*/
CREATE PROCEDURE test_proc3(int1 INTEGER,intab TYPETABLE)
       LANGUAGE SQLSCRIPT AS
BEGIN
       SELECT int1 AS "變數" FROM DUMMY;
       SELECT * FROM :intab;
END;
/*傳入引數,表*/
CALL test_proc3(1,TEST_PROC);
CALL test_proc3(2,"TEST_PROC");


/*建立procedure4*/
CREATE PROCEDURE test_proc4( IN intab TABLE( id INTEGER) DEFAULT EMPTY)
       LANGUAGE SQLSCRIPT AS
BEGIN
       IF IS_EMPTY(:intab) THEN
              SELECT 'input is empty' FROM DUMMY;
       ELSE
              SELECT 'input is not empty' FROM DUMMY;
       END IF;
END;
CALL test_proc4();

/*

2.1.3刪除procedure

DROP PROCEDURE <proc_name> [<drop_option>]

<proc_name> ::= [<schema_name>.]<identifier

<drop_option> ::= CASCADE | RESTRICT

CASCADE:級聯刪除,當procedure被其他procedure呼叫,級聯刪除

RESTRICT:當procedure被其他procedure呼叫,刪除時報錯

*/

DROP PROCEDURE test_proc1;

/*

2.1.4修改procedure

ALTER PROCEDURE <proc_name> [(<parameter_clause>)] [LANGUAGE <lang>]

[DEFAULT SCHEMA <default_schema_name>]

[READS SQL DATA] AS

BEGIN

[SEQUENTIAL EXECUTION] <procedure_body>

END

ALTER PROCEDURE <proc_name> RECOMPILE

通過生成更新執行計劃觸發重新編譯

*/

/*

2.1.5 procedure資訊

Table:SYS.PROCEDURES

可用的procedure資訊

表字段說明:

SCHEMA_NAME:shema名稱

PROCEDURE_NAME:procedure名稱

PROCEDURE_OID:procedure ID

SQL_SECURITY:SQL安全設定'DEFINER' / 'INVOKER'

DEFAULT_SCHEMA_NAME:Schema name of the unqualified objects in the procedure

INPUT_PARAMETER_COUNT:輸入引數數量

OUTPUT_PARAMETER_COUNT:輸出引數數量

INOUT_PARAMETER_COUNT:INOUT引數數量

RESULT_SET_COUNT:result set 計數

IS_UNICODE:是否包含 Unicode or not: 'TRUE'/ 'FALSE'

DEFINITION:procedure定義文字

PROCEDURE_TYPE:procedure型別

READ_ONLY:whether the procedure is read-only or not: 'TRUE'/ 'FALSE'

IS_VALID:Specifies whether the procedure is valid or not. This becomes 'FALSE' when its base objects are changed or dropped: 'TRUE'/ 'FALSE'

IS_HEADER_ONLY:Specifies whether the procedure is header-only procedure or not: 'TRUE'/'FALSE'

HAS_TRANSACTION_CONTROL_STATEMENTS:Specifies whether the procedure has transaction control statements or not:'TRUE'/'FALSE'

OWNER_NAME:Name of the owner of the procedure

TABLE:SYS.PROCEDURE_PARAMETERS

procedure的引數資訊

SCHEMA_NAME:Schema name of the stored procedure

PROCEDURE_NAME:Name of the stored procedure

PROCEDURE_OID:Object ID of the stored procedure

PARAMETER_NAME:Parameter name

DATA_TYPE_ID:Data type ID

DATA_TYPE_NAME: Data type name

LENGTH: Parameter length

SCALE:Scale of the parameter

POSITION :Ordinal position of the parameter

TABLE_TYPE_SCHEMA:Schema name of table type if DATA_TYPE_NAME is TABLE_TYPE

TABLE_TYPE_NAME: Name of table type if DATA_TYPE_NAME is TABLE_TYPE IS_INPLACE_TYPE VARCHER(5) Specifies whether the tabular parameter type is an inplace table type: 'TRUE'/'FALSE'

PARAMETER_TYPE: Parameter mode: 'IN', 'OUT', 'INOUT'

HAS_DEFAULT_VALUE:Specifies whether the parameter has a default value or not: 'TRUE', 'FALSE'

IS_NULLABLE:Specifies whether the parameter accepts a null value: 'TRUE', 'FALSE'

TABLE:SYS.OBJECT_DEPENDENCIES

物件之間的依賴關係,例如,引用特定表的檢視

BASE_SCHEMA_NAME : Schema name of the base object

BASE_OBJECT_NAME : Object name of the base object

BASE_OBJECT_TYPE : Type of the base object

DEPENDENT_SCHEMA_NAME : Schema name of the dependent object

DEPENDENT_OBJECT_NAME : Object name of the dependent object

DEPENDENT_OBJECT_TYPE : Type of the base dependent

DEPENDENCY_TYPE :ype of dependency between base and dependent object.

Possible values are:

0: NORMAL (default)

1: EXTERNAL_DIRECT (direct dependency between dependent object and base object)

2: EXTERNAL_INDIRECT (indirect dependency between dependent object und base object)

5: REFERENTIAL_DIRECT (foreign key dependency between tables)

TABLE:PROCEDURE_PARAMETER_COLUMNS

顯示procedure中定義的引數

SCHEMA_NAME:Schema name of the procedure

PROCEDURE_NAME:Name of the procedure

PROCEDURE_OID:Object ID of the procedure

PARAMETER_NAME:Parameter name

PARAMETER_POSITION : Ordinal position of the parameter

COLUMN_NAME : Name of the column of the parameter type

POSITION : Ordinal position of the column in a record

DATA_TYPE_NAME :SQL data type name of the column

LENGTH : Number of chars for char types, number of max digits for numeric types; number of chars for datetime types, number of bytes for LOB types

SCALE :Numeric types: the maximum number of digits to the right of the decimal point; time, timestamp: the decimal digits are defined as the number of digits to the right of the decimal point in the second's component of the data

IS_NULLABLE :Specifies whether the column is allowed to accept null value: 'TRUE'/'FALSE'

*/

SELECT * FROM SYS.PROCEDURES WHERE PROCEDURE_NAME = 'TEST_PROC2';
SELECT * FROM SYS. PROCEDURE_PARAMETERS WHERE PROCEDURE_NAME = 'TEST_PROC2';

/*依賴procedure建立*/
CREATE PROCEDURE test_proc_dep(IN a INTEGER,IN b INTEGER)
       LANGUAGE SQLSCRIPT AS
BEGIN
       SELECT a+b AS "sum" FROM DUMMY;
END;

CREATE PROCEDURE test_proc_dep1()
       LANGUAGE SQLSCRIPT AS
BEGIN
       CALL test_proc_dep(10,100);
END;
SELECT * FROM SYS.OBJECT_DEPENDENCIES WHERE DEPENDENT_OBJECT_NAME = 'TEST_PROC_DEP';

SELECT * FROM PROCEDURE_PARAMETER_COLUMNS WHERE PARAMETER_NAME = 'INTAB';

3.2 User-Defined Function

/*

2.2 User-Defined Function

兩種型別:

Table User-Defined Functions

Scalar UserDefined Functions

差異比較:

1.Functions Calling

A table UDF can only be called in the FROM-clause of an SQL statement in the same parameter positions as table names.

For example, SELECT * FROM myTableUDF(1)

A Scalar UDF can be called in SQL statements in the same parameter positions as table column names.

That takes place in the SELECT and WHERE clauses of SQL statements.

For example, SELECT myScalarUDF(1) AS myColumn FROM DUMMY

2.Input Parameter (輸入型別引數)

table UDF:

Primitive SQL type

Table types

Scalar UDF:

Primitive SQL type

Table types (with limitations)

3.Output

table UDF:

Must return a table whose type is defined in <return_type>.

Scalar UDF:

Must return scalar values specified in <return_parameter_list>.

4.Supported functionality

table UDF:

The function is tagged as read only by default.

DDL and DML are not allowed and only other read-only functions can be called.

Scalar UDF:

The function is tagged as a read-only function by default.

*/

/*

2.2.1 建立Function

語法:

CREATE [OR REPLACE] FUNCTION <func_name> [(<parameter_clause>)] RETURNS <return_type>

[LANGUAGE <lang>]

[SQL SECURITY <mode>]

[DEFAULT SCHEMA <default_schema_name>

[DETERMINISTIC]]

[WITH ENCRYPTION] AS

BEGIN

<function_body>

END

<func_name > ::= [<schema_name>.]<identifier>

<parameter_clause> ::= <parameter> [{,<parameter>}...]

<parameter> ::= [IN] <param_name> <param_type>

<param_type> ::= <sql_type> [ARRAY] | <table_type> | <table_type_definition> | <any_table_type>

<sql_type> ::= DATE | TIME | TIMESTAMP | SECONDDATE | TINYINT | SMALLINT | INTEGER | BIGINT

| DECIMAL | SMALLDECIMAL | REAL | DOUBLE | VARCHAR | NVARCHAR

| VARBINARY | CLOB | NCLOB | BLOB | ST_GEOMETRY| ARRAY

<table_type> ::= <identifier>

Scalar UDF可以使用<sql_type>,<table_type>,Array可以作為input,return引數。

SUDFs with table parameters can be used like any other SUDF with following exceptions:

1.Aliases (in FROM or WITH clauses) are not allowed.

2.Parameterized views, scripted calculation views or TUDFs as input are not supported.

3.ANY TABLE TYPE parameters are not supported.

4.SQLScript internal types, such as cursor variables or ROW types, are not supported.

Table UDF可以使用<sql_type>,<table_type>,Array

<table_type_definition> ::= TABLE (<column_list_definition>)

<column_list_definition > ::= <column_elem>[{, <column_elem>}...]

<column_elem> ::= <column_name> <data_type>

<column_name> ::= <identifier>

<return_type> ::= <return_parameter_list> | <return_table_type>

Scalar UDF返回值:

<return_parameter_list> ::= <return_parameter>[{, <return_parameter>}...]

<return_parameter> ::= <parameter_name> <sql_type> [ARRAY]

Table UDF返回table:

<return_table_type> ::= TABLE ( <column_list_definition> )

設定語言

LANGUAGE <lang>

<lang> ::= SQLSCRIPT

設定安全模式

SQL SECURITY <mode>

<mode> ::= DEFINER | INVOKER

設定預設schema

DEFAULT SCHEMA <default_schema_name>

<default_schema_name> ::= <unicode_name>

<function_body> ::= <scalar_function_body>|<table_function_body>

<scalar_function_body> ::= [DECLARE <func_var>] <proc_assign>

<table_function_body> ::= [<func_block_decl_list>] [<func_handler_list>] <func_stmt_list> <func_return_statement>

<func_block_decl_list> ::= DECLARE { <func_var>|<func_cursor>|<func_condition> }

<func_var>::= <variable_name_list> [CONSTANT] { <sql_type>| <array_datatype> } [NOT NULL][<func_default>];

<array_datatype> ::= <sql_type> ARRAY [ = <array_constructor> ]

<array_constructor> ::= ARRAY ( <expression> [{,<expression>}...] )

<func_default> ::= { DEFAULT | = } <func_expr>

<func_expr> ::= !!An element of the type specified by <sql_type>

<func_handler_list> ::= <proc_handler_list>

<func_stmt_list> ::= <func_stmt>| <func_stmt_list> <func_stmt>

<func_stmt> ::= <proc_block>

| <proc_assign> | <proc_single_assign>

| <proc_if> | <proc_while>

| <proc_for> | <proc_foreach>

| <proc_exit> | <proc_signal>

| <proc_resignal> | <proc_open>

| <proc_fetch> | <proc_close>

<func_return_statement> ::= RETURN <function_return_expr>

<func_return_expr> ::= <table_variable> | <subquery>

A table function must contain a return statement.

必須要有return語句

*/

--建立a table function
--返回table
CREATE FUNCTION scale (val INT)
  RETURNS TABLE (a NVARCHAR(20), b INT)
  LANGUAGE SQLSCRIPT AS
BEGIN   
  RETURN SELECT "Product_Name" as a, :val * "Quantity" AS  b FROM "MyProducts";
END;

--呼叫table function
SELECT * FROM scale(10);
SELECT * FROM scale(10) AS a,scale(20) as b where a.a = b.a;

--建立a scalar function
--返回兩個值的和,乘積
CREATE FUNCTION func_add_mul(x Double, y Double)
  RETURNS result_add Double, result_mul Double 
  LANGUAGE SQLSCRIPT READS SQL DATA AS
BEGIN    
  result_add = :x + :y;    
  result_mul = :x * :y;
END;

--呼叫scalar function
SELECT "Product_ID","Quantity","Price",func_add_mul("Quantity","Price").result_mul AS "Payment" FROM "MyProducts";

--可以在其他scalar function中呼叫function
CREATE FUNCTION func_multipy(x Double,y Double)
  RETURNS output1 double
  LANGUAGE SQLSCRIPT  AS
BEGIN   
       output1 = func_add_mul(:x,:y).result_add * func_add_mul(:x,:y).result_mul;
END;  
--呼叫function
SELECT func_multipy(2,2) as RESULT FROM dummy;

/*

2.2.2 修改function

ALTER FUNCTION <func_name>

RETURNS <return_type>

[LANGUAGE <lang>]

[DEFAULT SCHEMA <default_schema_name>] AS

BEGIN

<function_body>

END

*/

--獲取function
CREATE FUNCTION GET_FUNCTIONS
 RETURNS TABLE(schema_name NVARCHAR(256), name NVARCHAR(256))                                                    
 AS
BEGIN     
 RETURN SELECT schema_name AS schema_name,function_name AS name FROM FUNCTIONS;
END;

--呼叫function
SELECT * FROM GET_FUNCTIONS();

--修改function
ALTER FUNCTION GET_FUNCTIONS
 RETURNS TABLE(schema_name NVARCHAR(256), name NVARCHAR(256))                                                   
 AS
BEGIN     
 RETURN SELECT schema_name AS schema_name,function_name AS name FROM FUNCTIONS WHERE IS_VALID = 'TRUE';
END;

/*

2.2.3刪除function

DROP FUNCTION <func_name> [<drop_option>]

<func_name> ::= [<schema_name>.]<identifier>

<drop_option> ::= CASCADE | RESTRICT

如果沒有指定<drop_option>,執行non-cascade刪除,只刪除指定function,依賴function將失效;

cascade:級連刪除;

restrict:刪除function不能有依賴function,如果有報錯;

*/

DROP FUNCTION GET_FUNCTIONS;

/*

2.2.4 function引數

Table user-defined functions

Can have a list of input parameters and must return a table whose type is defined in <return type>

Input parameters must be explicitly typed and can have any of the primitive SQL type or a table type.

Scalar user-defined functions

Can have a list of input parameters and must returns scalar values specified in <return parameter list>.

Input parameters must be explicitly typed and can have any primitive SQL type.

Using a table as an input is not allowed.

*/

/*

2.2.5 Consistent Scalar Function Result

procedure中呼叫function,保持資料一致性。

*/

CREATE TABLE test_consistent(C1 VARCHAR(20));
CREATE FUNCTION func_count RETURNS v_result INTEGER AS
BEGIN  
       SELECT COUNT(*) INTO v_result FROM test_consistent;
END;

CREATE PROCEDURE proc_insert_delete AS
BEGIN   
       INSERT INTO test_consistent VALUES ('test');   
       SELECT 'TRACE 1: COUNT AFTER INSERT', COUNT(*) FROM test_consistent;   
       SELECT 'TRACE 2: COUNT DURING FUNCTION CALL', func_count() FROM DUMMY;   
       DELETE FROM test_consistent;   
       SELECT 'TRACE 3: COUNT AFTER DELETE', COUNT(*) FROM test_consistent;   
       COMMIT;
END;

--呼叫procedure
CALL proc_insert_delete;

/*

2.2.6 Function Metadata

SYS.FUNCTIONS:系統可用function;

SCHEMA_NAME:NVARCHAR(256) Schema name of the function

FUNCTION_NAME:NVARCHAR(256) Name of the function

FUNCTION_OID:BIGINT Object ID of the function

SQL_SECURITY:VARCHAR(7) SQL Security setting of the function:'DEFINER'/'INVOKER'

DEFAULT_SCHEMA_NAME:NVARCHAR(256) Schema name of the unqualified objects in the function

INPUT_PARAMETER_COUNT:INTEGER Input type parameter count

RETURN_VALUE_COUNT:INTEGER Return value type parameter count

IS_UNICODE:VARCHAR(5) Specifies whether the function contains Unicode or not: 'TRUE', 'FALSE'

DEFINITION:NCLOB Query string of the function

FUNCTION_TYPE:VARCHAR(10) Type of the function

FUNCTION_USAGE_TYPE:VARCHAR(9) Usage type of the function:'SCALAR', 'TABLE', 'AGGREGATE','WINDOW'

IS_VALID:VARCHAR(5) Specifies whether the function is valid or not. This becomes 'FALSE' when its base objects are changed or dropped: 'TRUE', 'FALSE'

IS_HEADER_ONLY:VARCHAR(5) Specifies whether the function is header-only function or not: 'TRUE'/'FALSE'

OWNER_NAME:NVARCHAR(256) Name of the owner of the function

SYS.FUNCTION_PARAMETERS:function的引數表

SCHEMA_NAME: NVARCHAR(256) Schema name of the function

FUNCTION_NAME: NVARCHAR(256) Name of the function

FUNCTION_OID: BIGINT Object ID of the function

PARAMETER_NAME: NVARCHAR(256) Parameter name

DATA_TYPE_ID: INTEGER Data type ID

DATA_TYPE_NAME: VARCHAR(16) Data type name

LENGTH: INTEGER Parameter length

SCALE: INTEGER Scale of the parameter

POSITION: INTEGER Ordinal position of the parameter

TABLE_TYPE_SCHEMA: NVARCHAR(256) Schema name of table type if DATA_TYPE_NAME is TABLE_TYPE

TABLE_TYPE_NAME: NVARCHAR(256) Name of table type if DATA_TYPE_NAME is TABLE_TYPE

IS_INPLACE_TYPE: VARCHAR(5) Specifies whether the tabular parameter type is an inplace table type: 'TRUE'/'FALSE'

PARAMETER_TYPE: VARCHAR(7) Parameter mode: IN, OUT, INOUT

HAS_DEFAULT_VALUE: VARCHAR(5) Specifies whether the parameter has a default value or not: 'TRUE', 'FALSE'

IS_NULLABLE: VARCHAR(5) Specifies whether the parameter accepts a null value: 'TRUE', 'FALSE'

FUNCTION_PARAMETER_COLUMNS:正在使用的table type

SCHEMA_NAME: NVARCHAR(256) Schema name of the function

FUNCTION_NAME: NVARCHAR(256) Name of the function

FUNCTION_OID: BIGINT Object ID of the function

PARAMETER_NAME: NVARCHAR(256) Parameter name

PARAMETER_POSITION: INTEGER Ordinal position of the parameter

COLUMN_NAME: NVARCHAR(256) Name of the column in the table parameter

POSITION: INTEGER Ordinal position of the column in the table parameter

DATA_TYPE_NAME: VARCHAR(16) SQL data type name of the column

LENGTH: INTEGER Number of chars for char types, number of max digits for numeric types; number of chars for datetime types, number of bytes for LOB types

SCALE INTEGER: Numeric types: the maximum number of digits to the right of the decimal point; time, timestamp: the decimal digits are defined as the number of digits to the right of the decimal point in the second's component of the data

IS_NULLABLE: VARCHAR(5) Specifies whether the column is allowed to accept null values: 'TRUE'/'FALSE'

設定function引數預設值

IN <param_name> (<sql_type>|<table_type>|<table_type_definition>) DEFAULT (<value>|<table_name>)

*/

SELECT * FROM FUNCTIONS;
--
SELECT * FROM FUNCTION_PARAMETERS;
--
SELECT * FROM FUNCTION_PARAMETER_COLUMNS;

--設定預設值,預設輸入引數,table型別
CREATE TABLE TEST_DEFAULT( s_type VARCHAR(10),s_name VARCHAR(20) );
INSERT INTO TEST_DEFAULT VALUES('type1','tom');
INSERT INTO TEST_DEFAULT VALUES('type2','jon');
CREATE FUNCTION func_default_value(
       IN INTAB TABLE(s_type VARCHAR (10), s_name VARCHAR (20)) DEFAULT "TEST_DEFAULT",
       IN delimiter VARCHAR(10) DEFAULT ':')
       RETURNS TABLE(fullstring VARCHAR(40)) AS
BEGIN   
       RETURN SELECT s_type||:delimiter||s_name AS fullstring FROM :INTAB;    
END;

--呼叫function
SELECT * FROM func_default_value();

--不使用預設值
SELECT * FROM func_default_value(delimiter=>',');

/*

2.2.7 SQL嵌入function

*/

--SQL語句使用table function
CREATE FUNCTION TEMP_FUNC()
 RETURNS TABLE (A INT, B INT, C INT) AS
 BEGIN      
      DECLARE buffer TABLE (A INT, B INT, C INT);       
      :buffer.insert(( 1, 2, 3));       
      :buffer.insert(( 1, 2, 4));       
      :buffer.insert(( 2, 3, 2));       
      :buffer.insert(( 2, 3, 4));       
      :buffer.insert(( 2, 5, 7));       
      RETURN :buffer;
 END;

SELECT A, B, SUM(C) FROM TEMP_FUNC()
       GROUP BY A, B
       ORDER BY A, B;
--SQL嵌入table function
SELECT A, B, SUM(C) FROM
       SQL FUNCTION       
             RETURNS TABLE (A INT, B INT, C INT)       
       BEGIN              
              DECLARE buffer TABLE (A INT, B INT, C INT);              
              :buffer.i nsert((1, 2, 3));              
              :buffer.i nsert((1, 2, 4));             
              :buffer.i nsert((2, 3, 2));              
              :buffer.i nsert((2, 3, 4));              
              :buffer.i nsert((2, 5, 7));              
              RETURN :buffer;       
       END
       GROUP BY A, B
       ORDER BY A, B;

-- input parameter
SELECT a FROM 
       SQL FUNCTION (IN a INT => 1) 
    RETURNS TABLE(a INT) 
    BEGIN  
           RETURN SELECT :a AS a FROM dummy; 
    END;

-- nested SQL FUNCTION clause
SELECT a FROM SQL FUNCTION
       RETURNS TABLE (a int) 
       BEGIN  
              RETURN SELECT * FROM SQL FUNCTION   
                     RETURNS TABLE (a int)     
                     BEGIN       
                       RETURN SELECT 1 AS a FROM dummy;     
                     END;
       END;

/*

2.2.8 Deterministic Scalar Functions

Deterministic Scalar Functions相同條件總是返回確定值

2.2.9 Procedure Result Cache

PRC:過程結果快取,以輸入引數作為key,輸出引數作為值;

注意:PRC is enabled only for deterministic procedures

*/

--建立deterministic function
--deterministic??不支援

/*
CREATE FUNCTION func_deterministic(IN a INT)
 RETURNS ret INT deterministic AS
 BEGIN
      ret = :a;
 END;
SELECT func_deterministic("A") FROM "TEST";
*/

--建立deterministic procedure
--deterministic??不支援
/*
create procedure add (in a int, in b int, out c int) deterministic as
begin
       c = :a + :b;
end
*/

3.3 User-Defined Libraries

/*

2.3 User-Defined Libraries

定義一組variable、procedures,functions;

建立Library

CREATE [OR REPLACE] LIBRARY <lib_name>

[LANGUAGE SQLSCRIPT] [DEFAULT SCHEMA <default_schema_name>] AS

BEGIN

[<lib_var_decl_list>] [<lib_proc_func_list>]

END;

修改Library

ALTER LIBRARY <lib_name>

[LANGUAGE SQLSCRIPT] [DEFAULT SCHEMA <default_schema_name>] AS

BEGIN

[<lib_var_decl_list>] [<lib_proc_func_list>]

END;

刪除Library

DROP LIBRARY <lib_name>;

<lib_name> ::= [<schema_name>.]<identifier>;

<lib_var_decl_list> ::= <lib_var_decl> [{<lib_var_decl>}...]

<lib_var_decl> ::= <access_mode> <var_decl> ;

<var_decl> ::= VARIABLE <member_name> [CONSTANT] <sql_type> [NOT NULL] [<proc_default>]

<access_mode> ::= PUBLIC | PRIVATE <member_name> ::= <identifier>

<proc_default> ::= { DEFAULT | '=' } <expression>

<lib_proc_func_list> ::= <lib_proc_func> [{<lib_proc_func>}...]

<lib_proc_func> ::= <access_mode> <proc_func_def> ;

<proc_func_def> ::= <proc_def> | <func_def>

<proc_def> ::= PROCEDURE <member_name> [<parameter_clause>] [<proc_property>] AS

BEGIN

[SEQUENTIAL EXECUTION] <procedure_body>

END

<proc_property> ::= [LANGUAGE <lang>] [SQL SECURITY <mode>] [READS SQL DATA]

<func_def> ::= FUNCTION <member_name> [<parameter_clause>] RETURNS <return_type> [<func_property>] AS

BEGIN

<function_body>

END

<func_property> ::= [LANGUAGE <lang>] [SQL SECURITY <mode>] [READS SQL DATA]

兩種型別Library:built-in libraries:系統提供;

user-defined libraries:使用者定義;

Library僅可以使用在Procedures,functions.

Library Members:

<procedure_body> ::= [<proc_using_list>] [<proc_handle_list>] <proc_stmt_list>

<proc_using_list> ::= {<proc_using>}...

<proc_using> ::= USING <lib_name> AS <lib_alias> ;

<lib_name> ::= [<schema_name>.]<identifier>

<lib_alias> ::= <identifier>

<lib_member_ref> ::= [ <schema_name> . ] <identifier> ':' <member_name>

<proc_assign> ::= <variable_name> = { <expression> | <array_function> | <lib_member_func_call>} ;

| <variable_name> '[' <expression> ']' = { <expression> | <lib_member_func_call> } ;

| <lib_member_ref> = { <expression> | <lib_member_func_call> } ;

<lib_member_func_call> ::= <lib_member_ref> ( [<expression> [ {, <expression> }...] ] )

<proc_call> ::= CALL <proc_name> ( <param_list> ) ;

| CALL <lib_member_ref> ( <param_list> ) ;

LIBRARIES

所有有效的Libraries

SCHEMA_NAME: Schema name of the library

LIBRARY_NAME: Name of the library

LIBRARY_OID: Object ID of the library

OWNER_NAME: Owner name of the library

DEFAULT_SCHEMA_NAME: Schema of the unqualified objects in the library

DEFINITION: Definition of the library

LIBRARY_TYPE: Language type of the library

IS_VALID: Specifies whether the library is valid or not. This becomes false when its base objects are changed or dropped.

CREATE_TIME: Creation time

LIBRARY_MEMBERS

Library members資訊

SCHEMA_NAME: Schema name of the library

LIBRARY_NAME: Name of the library

LIBRARY_OID: Object ID of the library

MEMBER_NAME: Name of the library member

MEMBER_TYPE: Type of the library member: 'VARIABLE', 'PROCEDURE', 'FUNCTION'

ACCESS_MODE: Access mode of the library member: 'PUBLIC', 'PRIVATE'

DEFINITION: Definition string of the library member

UDL Member Procedure Call Without SQLScript Artifacts

<call_stmt> ::= CALL <proc_name> ( <param_list> ) [WITH OVERVIEW] [IN DEBUG MODE]

| CALL <lib_member_ref> ( <param_list> );

<proc_call> ::= CALL <proc_name> ( <param_list> ) ;

| CALL <lib_member_ref> ( <param_list> ) ;

<lib_member_ref> ::= [<schema_name> '.'] <library_name_or_alias> ':' <member_name>

<schema_name> ::= <identifier>

<library_name_or_alias> ::= <identifier>

<member_name> ::= <identifier>

Library Member Functions and Variables

Library member functions and variables can be used directly in SQL or expressions in SQLScript.

可以直接在SQL中使用

<expression> ::= <case_expression> | <function_expression> | ... | <variable_name> | ...

<function_expression> ::= <function_name> ( <expression> [{, <expression} ...])

<function_name> ::= [[ <database_name> '.' ] <schema_name> '.' ]] <identifier> | <lib_member_ref>

<variable_name> ::= <identifier> | <lib_member_ref>

<from_clause> ::= FROM <table_expression> [, <table_expression> ...]

<table_expression> ::= <table_ref> | ... | <function_reference> | ...

<function_reference> ::= <function_name> ( <proc_arg_list> | <opt_parameter_key_value_list> )

<lib_member_ref> ::= [<schema_name> '.' ] <library_name_or_alias> ':' <member_name>

<schema_name> ::= <identifier>

<library_name_or_alias> ::= <identifier>

<member_name> ::= <identifier>

*/

/*--建立Library*/
--for 語句建立表插入資料
create table test_data_table(col1 int);
do begin 
      declare idx int = 0; 
      for idx in 1..200 do   
             insert into test_data_table values (:idx); 
      end for;
end;

--建立library
create LIBRARY lib_test1 as begin
       public variable maxval constant int = 100;
       public function bound_with_maxval(i int) returns x int as begin   
              x = case when :i > :maxval then :maxval else :i end; 
     end;
       public procedure get_data(in size int, out result table(col1 int)) as begin   
              result = select top :size col1 from test_data_table; 
     end;
end;

--procedure使用library
create procedure proc_test1 (in inval int) as
begin
   using lib_test1 as mylib; 
   declare var1 int = mylib:bound_with_maxval(:inval);
   if :var1 > mylib:maxval then   
     select 'unexpected' from dummy; 
   else   
     declare tv table (col1 int);   
     call mylib:get_data(:var1, tv);   
     select count(*) from :tv; 
   end if;
end;

 
/*Libraries相關資訊*/
--LIBRARIES資訊
SELECT * FROM LIBRARIES;
--不存在?
SELECT * FROM LIBRARY_MEMBERS;

/*UDL Member Procedure Call Without SQLScript Artifacts*/
--呼叫library時,必須在匿名block或者procedure,function中,現在可以直接呼叫
create library mylib as begin
   public procedure memberproc(in i int, out tv table(col1 nvarchar(10))) as begin   
     tv = select :i * 100 as col1 from dummy; 
     end;
end;

do (in iv int => 1, out otv table(col1 nvarchar(10)) => ?) begin  using mylib as mylib;
       call mylib:memberproc(:iv, otv);
end;

--直接呼叫library
create library mylib as begin
   public procedure memberproc(in i int, out tv table(col1 nvarchar(10))) as begin   
     tv = select :i * 100 as col1 from dummy; 
   end;
end;
call mylib:memberproc(1, ?);

 
/*Library Member Functions and Variables*/
--建立表插入資料
create table test_r_tab (r decimal);
insert into test_r_tab values (50);
insert into test_r_tab values (100);

--建立library
create library lib_test2 as begin 
       public variable pi constant decimal = 3.14; 
       public function circumference(r decimal) returns a int as begin   
              a = 2 * :pi * :r;
       end; 
       public function circumference_table(r_table table(r decimal)) returns table(c decimal) as begin   
              return select 2 * :pi * r as c from :r_table; 
       end;
 end;

 --直接SQL呼叫
select lib_test2:circumference(10) from dummy;

3.4 Create or Replace

當建立Function,Procedure時,使用OR REPLACE建立或者替換Function, Procedure。

示例:

/*

2.4CREATE OR REPLACE

建立Function,Procedure時,使用OR REPLACE修改function,procedure.

CREATE [OR REPLACE] FUNCTION <function_name>

[(<parameter_clause>)]

RETURNS <return_type>

[LANGUAGE <lang>]

[SQL SECURITY <mode>]

[DEFAULT SCHEMA <default_schema_name>]

[DETERMINISTIC]

[WITH ENCRYPTION] AS

{ BEGIN <function_body> END | HEADER ONLY }

[WITH [<cache_type>]

CACHE RETENTION <minute_value>

[OF <projection_list>]

[FILTER <filter_condition>]]

CREATE [OR REPLACE] PROCEDURE <procedure_name>

[(<parameter_clause>)]

[LANGUAGE <lang>]

[SQL SECURITY <mode>]

[DEFAULT SCHEMA <default_schema_name>]

[{ ROUTE TO REMOTE SOURCE <name_list>

| ROUTE TO VOLUME <volume_id_list>

| ROUTE BY TABLE <hint_table_list> }]

[DETERMINISTIC] [WITH ENCRYPTION] AS

{ BEGIN <procedure_body> END | HEADER ONLY

"測試時環境不支援,OR REPLACE

*/

CREATE PROCEDURE test_proc5 as
begin  
    select * from dummy;
end;
call test_proc5();

--報錯:number of parameters cannot be changed with ALTER command
--可以更改<body>中內容
ALTER PROCEDURE test_proc5() as
begin   
    select 1 from dummy;   
end;
call test_proc5();

--replace procedure
-- new parameter
-- add default parameter value
-- change the number of parameter and name of parameter
--?報錯,不支援CREATE OR REPLACE
CREATE OR REPLACE PROCEDURE test_proc5(IN a INT) as
begin  
    select a from dummy;
end;
call test_proc5(1);

3.5 Anonymous Block

建立匿名程式碼塊

示例:

/*

2.5Anonymous Block

匿名程式碼塊

語法:

DO [(<parameter_clause>)]

BEGIN [SEQUENTIAL EXECUTION]

<body>

END WITH HINT (...)

<body>內容和procedure中一致

<parameter_clause> ::= <named_parameter> [{,<named_parameter>}...]

<named_parameter> ::= (IN|OUT) <param_name> <param_type> => <proc_param>

*/

DO (IN in_var NVARCHAR(20)=> 'P1',OUT outtab TABLE (A NVARCHAR(20),B NVARCHAR(20)) => ?)
BEGIN   
    T1 = SELECT "Product_ID" AS A,"Product_Name" AS B  FROM "MyProducts" WHERE "Product_ID" = in_var;      
    outtab = SELECT * FROM :T1;   
END

--block with hint
--報錯不支援
DO BEGIN
   DECLARE i INT; 
   FOR i in 1..5 DO   
     SELECT * FROM dummy;
   END FOR;
END WITH HINT(dev_se_use_llvm)

--block建立table,插入資料
DO BEGIN   
    DECLARE I INTEGER;   
    CREATE TABLE MYTAB4(I INTEGER);    
    FOR I IN 1..10 DO       
         INSERT INTO MYTAB4 VALUES (:I);   
    END FOR;
END

3.6 SQLScript Encryption

示例:

/*

2.6 SQLScript Encryption

定義時使用[WITH ENCRYPTION]

[CREATE | ALTER] PROCEDURE <proc_name> [(<parameter_clause>)]

[LANGUAGE <lang>]

[SQL SECURITY <mode>]

[DEFAULT SCHEMA <default_schema_name>]

[READS SQL DATA ]

[<sqlscript_route_option>]

[WITH ENCRYPTION]

AS BEGIN ... END;

[CREATE | ALTER] FUNCTION <func_name> [(<parameter_clause>)] RETURNS <return_type>

[LANGUAGE <lang>]

[SQL SECURITY <mode>]

[DEFAULT SCHEMA <default_schema_name>]

[READS SQL DATA]

[<sqlscript_route_option>]

[DETERMINISTIC]

[WITH ENCRYPTION]

AS BEGIN ... END;

"已經建立的Procedure,function,設定加密

ALTER PROCEDURE <proc_name> ENCRYPTION ON;

ALTER FUNCTION <func_name> ENCRYPTION ON;

*/

--沒有IS_ENCRYPTED列
SELECT * FROM  PROCEDURES;
SELECT * FROM FUNCTIONS;

--?with encryption報錯
create procedure test_encry_proc with encryption as
begin 
 select 1 as i from dummy;
end;