数据库
首页 > 数据库> > 第十二章 SQL命令 CREATE QUERY

第十二章 SQL命令 CREATE QUERY

作者:互联网

文章目录

第十二章 SQL命令 CREATE QUERY

创建Query

大纲

CREATE QUERY queryname(parameter_list) [characteristics] 
   [ LANGUAGE SQL ]
   BEGIN
code_body ;
   END

CREATE QUERY queryname(parameter_list) [characteristics] 
    LANGUAGE OBJECTSCRIPT
   { code_body }

参数

描述

CREATE QUERY语句在类中创建一个查询。
默认情况下,名为MySelect的查询将被存储为User.queryMySelectSQLUser.queryMySelect

CREATE QUERY创建的查询可能作为存储过程公开,也可能不作为存储过程公开。
要创建公开为存储过程的查询,必须指定procedure关键字作为其特征之一。
还可以使用CREATE PROCEDURE语句创建作为存储过程公开的查询。

为了创建查询,必须拥有%CREATE_QUERY管理权限,如GRANT命令所指定的。如果试图为已定义所有者的现有类创建查询,则必须以该类的所有者身份登录。否则,操作将失败,并出现SQLCODE -99错误。

如果类定义是已部署的类,则不能在类中创建查询。此操作失败,出现SQLCODE -400错误,出现%msgUnable to execute DDL that modifies a deployed class: 'classname'

参数

queryname

要创建为存储过程的查询的名称。此名称可以是非限定名称(StoreName)并采用默认架构名称,也可以通过指定架构名称(Patient.StoreName)进行限定。可以使用$SYSTEM.SQL.Schema.Default()方法来确定当前系统范围内的默认架构名称。系统范围内的初始默认模式名是SQLUser,它对应于类包名User

注意,FOR特征(将在下面描述)覆盖queryname中指定的类名。
如果已经存在具有此名称的方法,则操作将失败,并出现SQLCODE -361错误。

生成的类的名称是对应于架构名称的包名,后跟一个点,后跟“query”,后跟指定的queryname。例如,如果非限定查询名RandomLetter采用初始默认模式SQLUser,则得到的类名将是:User.queryRandomLetter

SQL不允许指定只以字母大小写不同的查询名。
指定一个与现有查询名称仅在字母大小写上不同的查询名称将导致SQLCODE -400错误。

如果指定的queryname已经存在于当前命名空间中,系统将生成SQLCODE -361错误。

parameter-list

用于将值传递给查询的参数的参数声明列表。
形参列表用圆括号括起来,列表中的形参声明用逗号分隔。
括号是必须的,即使没有指定参数。

列表中的每个参数声明由(按顺序)组成:

下面的示例创建了一个公开为存储过程的查询,该存储过程具有两个输入参数,这两个参数都具有默认值。
topnum输入参数指定可选的DEFAULT关键字;
minage输入参数忽略了这个关键字:

CREATE QUERY AgeQuery(IN topnum INT DEFAULT 10,IN minage INT 20)
   PROCEDURE
   BEGIN
   SELECT TOP :topnum Name,Age FROM Sample.Person
   WHERE Age > :minage ;
   END

以下是该查询的所有有效CALL语句:Call AgeQuery(6,65);Call AgeQuery(6);Call AgeQuery(,65);Call AgeQuery()

CALL AgeQuery(6,65); CALL AgeQuery(6); CALL AgeQuery(,65); CALL AgeQuery()

在这里插入图片描述

characteristics

可用的特征关键字如下:

如果指定的方法关键字(如PRIVATERETURNS)对查询无效,系统将生成SQLCODE-47错误。指定重复特征会导致SQLCODE-44错误。

SELECTMODE子句指定返回数据的模式。如果模式值是逻辑值,则返回逻辑值(内部存储)。例如,日期以$HOROLOG格式返回。如果模式值为ODBC,则应用逻辑到ODBC的转换,并返回ODBC格式值。如果模式值为DISPLAY,则应用逻辑到显示的转换,并返回显示格式值。如果模式值为RUNTIME,则可以通过设置%SQL.Statement%SelectMode属性在执行时设置模式(设置为LOGICALODBCDISPLAY),运行时模式的值为Logical。为SELECTMODE指定的值将添加到ObjectScript类方法代码的开头:#SQLCompile select=mode

RESULTS子句指定查询的结果。RESULTS子句中的SQL数据类型参数被转换为查询的ROWSPEC中相应的 IRIS数据类型参数。例如,RESULTS子句RESULTS(Code VARCHAR(15))生成ROWSPEC范ROWSPEC=“Code:%Library.String(MAXLEN=15)”

LANGUAGE

指定CODE_BODY使用的语言的关键字子句。允许的子句是Language OBJECTSCRIPTLanguage SQL。如果省略LANGUAGE子句,则默认为SQL

如果语言是SQL,则会生成%Library.SQLQuery类型的类查询。如果语言是OBJECTSCRIPT,则会生成%Library.Query类型的类查询。

code_body

要创建的查询的程序代码。可以在SQL或ObjectScript中指定此代码。使用的语言必须与LANGUAGE子句匹配。但是,在ObjectScript中指定的代码可以包含嵌入式SQL

如果指定的代码是SQL,则它必须由单个SELECT语句组成。SQL中查询的程序代码以BEGIN关键字开头,后跟程序代码(SELECT语句)。在程序代码的末尾,指定分号(),然后指定END关键字。

如果指定的代码是OBJECTSCRIPT,则它必须包含对 IRIS提供的%Library.Query类的Execute()Fetch()类方法的调用,并且可以包含Close()FetchRows()GetInfo()方法调用。ObjectScript代码用大括号括起来。如果EXECUTE()FETCH()丢失,则编译时会生成SQLCODE-46错误。

如果ObjectScript代码块将数据提取到局部变量(例如,Row)中,则必须以行set Row=""结束代码块,以指示数据结束条件。

如果查询公开为存储过程(通过在Characteristic中指定PROCEDURE关键字),则它使用过程上下文处理程序在过程及其调用方之间来回传递过程上下文。

调用存储过程时,%Library.SQLProcContext类的对象在%sqlcontext变量中实例化。这用于在过程及其调用者(例如,ODBC服务器)之间来回传递过程上下文。

%sqlcontext由几个属性组成,包括错误对象、SQLCODE错误状态、SQL行数和错误消息。下面的示例显示了用于设置其中几个值的值:

  SET %sqlcontext.%SQLCODE=SQLCODE
  SET %sqlcontext.%ROWCOUNT=%ROWCOUNT
  SET %sqlcontext.%Message=%msg

SQLCODE%ROWCOUNT的值由SQL语句的执行自动设置。每次执行前都会重置%sqlcontext对象。

或者,可以通过实例化%SYSTEM.Error对象并将其设置为%sqlcontext.Error来建立错误上下文。

IRIS使用提供的代码生成查询的实际代码。

示例

下面的嵌入式SQL示例创建名为DocTestPersonState的查询。它不声明任何参数,设置SELECTMODE特征,并采用默认语言(SQL):

ClassMethod CreateQuery()
{
	&sql(
		CREATE QUERY DocTestPersonState() SELECTMODE RUNTIME
			BEGIN
				SELECT Name,Home_State FROM Sample.Person ;
			END
	)
	if SQLCODE=0 { 
		w !,"创建查询" 
	} elseif SQLCODE=-361 { 
		w !,"查询存在: ",%msg 
	} else { 
		w !,"创建 QUERY 错误 ",SQLCODE 
	}
}

可以转到管理门户,选择Classes选项,然后选择Samples命名空间。将在那里找到由上面的示例创建的查询:User.queryDocTestPersonState.cls。在重新运行上面的程序示例之前,您可以从该显示中删除此查询。当然,可以使用DROP QUERY删除创建的查询。

Class User.queryDocTestPersonState Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {yx}, Not ProcedureBlock ]
{

Query DocTestPersonState() As %Library.SQLQuery(SELECTMODE = "RUNTIME")
{
	SELECT Name,Home_State FROM Sample.Person
}

}

下面的嵌入式SQL示例创建一个名为DocTestSQLCODEList的基于方法的查询,该查询获取SQLCODE及其说明的列表。它设置结果结果集特征,将语言设置为ObjectScript,并调用Execute()Fetch()Close()方法:

ClassMethod CreateQuery1()
{
	&sql(
		CREATE QUERY DocTestSQLCODEList()
			RESULTS 
			(
				SQLCODE SMALLINT, Description VARCHAR(100)
			)
			PROCEDURE
			LANGUAGE OBJECTSCRIPT
			Execute(INOUT QHandle BINARY(255))
			{
				s QHandle=1, %i(QHandle)=""
				q ##lit($$$OK)
			}
			Fetch(INOUT QHandle BINARY(255), INOUT Row %List, INOUT AtEnd INT)
			{
				s AtEnd = 0, Row = ""
				s %i(QHandle) = $o(^%qCacheSQL("SQLCODE", %i(QHandle)))
				if %i(QHandle) = "" {
					s AtEnd = 1 q ##lit($$$OK) 
				}
				s Row = $lb(%i(QHandle), ^%qCacheSQL("SQLCODE", %i(QHandle), 1, 1))
				q ##lit($$$OK)
			}
			Close(INOUT QHandle BINARY(255))
			{
				k %i(QHandle)
				q ##lit($$$OK)
			}
	)
	if SQLCODE=0 { 
		w !,"创建查询" 
	} elseif SQLCODE=-361 { 
		w !,"查询存在: ",%msg 
	} else { 
		w !,"创建 QUERY 错误 ",SQLCODE _ " "_%msg 
	}
}

可以转到管理门户,选择Classes选项,然后选择Samples命名空间。将在那里找到由上面的示例创建的查询:User.queryDocTestSQLCODEList.cls。在重新运行上面的程序示例之前,可以从该显示中删除此查询。当然,可以使用DROP QUERY删除创建的查询。

下面的动态SQL示例创建名为DocTest的查询,然后使用%SQL.Statement类的%PrepareClassQuery()方法执行此查询:

ClassMethod CreateQuery2()
{
	s SQLCODE = 0
	/* 创建 Query */
	s myquery=4
	s myquery(1) = "CREATE QUERY DocTest() SELECTMODE RUNTIME "
	s myquery(2) = "BEGIN "
	s myquery(3) = "SELECT TOP 5 Name,Home_State FROM Sample.Person ; "
	s myquery(4) = "END"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(.myquery)
	if qStatus '= 1 {
		w "%Prepare 失败:" DO $System.Status.DisplayError(qStatus) 
		q
	}
	s rset = tStatement.%Execute()
	if SQLCODE = 0 { 
		w !,"创建查询" 
	} elseif SQLCODE=-361 { 
		w !,"查询存在: ",%msg 
	} else { 
		w !,"创建 QUERY 错误 ",SQLCODE _ " "_%msg 
	}
	/* 调用 Query */
	w !,"调用 Query",!
	s cqStatus = tStatement.%PrepareClassQuery("User.queryDocTest","DocTest")
	if cqStatus'=1 {
		w "%PrepareClassQuery 失败:" 
		d $System.Status.DisplayError(cqStatus)
	}
	s rset = tStatement.%Execute()
	w "Query 数据",!,!
	while rset.%Next() {
		d rset.%Print() 
	} 
	w !,"结束结束"
	/* 删除 Query */
	&sql(DROP QUERY DocTest)
	if SQLCODE = 0 { 
		w !,"删除 Query" 
	}
}

标签:创建,CREATE,指定,查询,SQLCODE,SQL,QUERY
来源: https://blog.csdn.net/yaoxin521123/article/details/120232933