#
第八章 SQL命令 CREATE METHOD(一) 在类中创建方法。 # 大纲 ```sql CREATE [STATIC] METHOD name (parameter_list) [ characteristics ] [ LANGUAGE SQL ] BEGIN code_body ; END CREATE [STATIC] METHOD name (parameter_list) [ characteristics ] LANGUAGE OBJECTSCRIPT { code_body } ``` # 参数 - `name` - 要在存储过程类中创建的方法的名称。 名称必须是有效的标识符。 过程名可以是限定的(`schema.procname`),也可以是非限定的(`procname`)。 非限定过程名接受默认模式名。 名称后面必须跟括号,即使没有指定参数。 - `parameter_list` - 可选——传递给方法的参数列表。 参数列表用圆括号括起来,列表中的参数用逗号分隔。 即使没有指定参数,括号也是必须的。 - `characteristics` - 可选—指定方法特征的一个或多个关键字。 允许的关键字是`RETURNS`, `FOR`, `FINAL`, `PRIVATE`, `PROCEDURE`, `SELECTMODE`。可以指定特征关键字短语`RESULT SETS`、`DYNAMIC RESULT SETS`或`DYNAMIC RESULT SETS n`,其中`n`是整数。 这些短语是同义词; `DYNAMIC`关键字和`n`整数为`no-ops`,提供兼容性。多个特征由空格(一个空格或换行符)分隔。 特性可以以任何顺序指定。 - `LANGUAGE OBJECTSCRIPT` ,`LANGUAGE SQL` - 可选—用于代码体的编程语言。指定语言对象脚本(对于对象脚本)或语言`SQL`。如果省略了`LANGUAGE`子句,则默认为`SQL`。 - `code_body` - 方法的程序代码。`SQL`程序代码以`BEGIN`关键字开头,以`END`关键字结尾。`code_body`中的每个完整的SQL语句都以分号(`;`).ObjectScript程序代码用花括号括起来。 ObjectScript代码行必须缩进。 # 描述 `CREATE METHOD`语句创建一个类方法。 这个类方法可能是存储过程,也可能不是。 要在公开为`SQL`存储过程的类中创建方法,必须指定`procedure`关键字。 默认情况下,`CREATE METHOD`不会创建一个同时也是存储程序的方法; `CREATE PROCEDURE`语句总是创建一个同时也是存储过程的方法。 提供可选的`STATIC`关键字是为了说明所创建的方法是一个静态(类)方法,而不是一个实例方法。 该关键字没有提供实际的功能。 为了创建方法,必须具有`GRANT`命令指定的`%CREATE_METHOD`管理权限。 如果试图为具有已定义所有者的现有类创建方法,则必须作为该类的所有者登录。 否则,操作将失败,并出现`SQLCODE -99`错误。 如果类定义是已部署的类,则不能在类中创建方法。 此操作失败,并出现一个带有`%msg`的`SQLCODE -400`错误`Unable to execute DDL that modifies a deployed class: 'classname'.` 下面两个示例都展示了相同类方法的创建。 第一个示例使用`CREATE METHOD`,第二个示例在类`User`中定义类方法。 字母: ```sql CREATE METHOD RandCaseLetter(IN caps CHAR) RETURNS INTEGER PROCEDURE LANGUAGE OBJECTSCRIPT { :Top if caps = "U" { s x = $random(91) if x > 64 { q $char(x) } else { g Top } } elseif caps="L" { s x = $random(123) if x > 97 { q $char(x) } else { g Top } } else { q "大小写必须 'U' 或 'L'" } } } ``` 自动创建的后台类 ```java Class User.methRandCaseLetter Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {yx}, Not ProcedureBlock ] { ClassMethod RandCaseLetter(caps As %Library.String(MAXLEN=1)) As %Library.Integer(MAXVAL=2147483647,MINVAL=-2147483648) [ SqlName = RandCaseLetter, SqlProc ] { Top IF caps="U" {SET x=$RANDOM(91) IF x>64 {QUIT $CHAR(x)} ELSE {GOTO Top}} ELSEIF caps="L" {SET x=$RANDOM(123) IF x>97 {QUIT $CHAR(x)} ELSE {GOTO Top}} ELSE {QUIT "case must be 'U' or 'L'"} } } ``` ```java Class User.Letters Extends %Persistent [ DdlAllowed ] { ClassMethod RandCaseLetter(caps) As %String [ SqlName = RandomLetter, SqlProc ] { Top if caps = "U" { s x = $random(91) if x > 64 { q $char(x) } else { g Top } } elseif caps="L" { s x = $random(123) if x > 97 { q $char(x) } else { g Top } } else { q "大小写必须 'U' 或 'L'" } } } ``` # 参数 ## name 要创建的方法的名称。 此名称可以是非限定的(`StoreName`)并接受系统范围的默认模式名称,也可以通过指定模式名称(`Patient.StoreName`)进行限定。 可以使用`$SYSTEM.SQL.Schema.Default()`方法确定当前系统范围的默认模式名。 系统范围的初始默认模式名是`SQLUser`,它对应于类包名`User`。 注意,`FOR`特征(将在下面描述)覆盖了`name`中指定的类名。 如果已经存在具有此名称的方法,则操作将失败,并出现`SQLCODE -361`错误。 生成的类的名称是与模式名对应的包名,后面跟着一个点,然后是`“meth”`,最后是指定的名称。 例如,如果非限定方法名`RandomLetter`接受初始默认模式`SQLUser`,则产生的类名将是:`User.methRandomLetter`。 ## parameter-list 用于将值传递给方法的参数列表。 形参列表用圆括号括起来,列表中的形参声明用逗号分隔。 即使没有指定参数,括号也是必须的。 列表中的每个参数声明由(按顺序)组成: - 一个可选关键字,指定参数模式是`IN`(输入值)、`OUT`(输出值)还是`INOUT`(修改值)。 如果省略,默认参数模式为`IN`。 - 参数名称。 参数名称区分大小写。 - 参数的数据类型。 - 可选:默认值。 可以指定`DEFAULT`关键字后跟一个默认值; `DEFAULT`关键字是可选的。 如果没有指定默认值,则假定默认值为`NULL`。 方法的输出值自动从`Logical`格式转换为`Display/ODBC`格式。 默认情况下,方法的输入值不会从`Display/ODBC`格式转换为`Logical`格式。 但是,可以使用`$SYSTEM.SQL.Util.SetOption("SQLFunctionArgConversion")`方法在系统范围内配置输入显示到逻辑的转换。 可以使用`$SYSTEM.SQL.Util.GetOption("SQLFunctionArgConversion")`来确定该选项的当前配置。 下面的示例指定两个输入参数,它们都有默认值。 为第一个参数指定可选的`DEFAULT`关键字,为第二个参数省略: ```sql CREATE METHOD RandomLetter(IN firstlet CHAR DEFAULT 'A',IN lastlet CHAR 'Z') BEGIN -- SQL program code END ```