0 关注者 · 478 帖子

SQL 是在关系数据库中存储、操作和检索数据的标准语言。

文章 姚 鑫 · 二月 1, 2022 4m read

第四十一章 SQL函数 DATE

接受时间戳并返回日期的函数。

大纲

DATE(timestamp)

参数

  • timestamp - 指定时间戳或其他日期或日期和时间表示形式的表达式。

描述

Date接受时间戳表达式并返回日期。返回值的数据类型为Date。这在功能上与CAST相同(时间戳与日期相同)。它接受具有以下任何数据类型类(或其子类)的时间戳值:%Library.TimeStamp%Library.PosiTime%Library.Date%Library.Integer%Library.Numerical(用于隐式逻辑日期,如+$HOROLOG)。它还可以接受格式与%Library.TimeStamp(有效的ODBC日期)兼容的%Library.String值。

无效的ODBC日期字符串的计算结果为零,与日期1840年12月31日相对应。时间戳可以只包含ODBC格式的日期或ODBC格式的日期和时间。虽然只转换ODBC时间戳的日期部分,但会验证整个字符串。如果日期部分不完整、日期或时间部分包含超出范围的值(包括闰年计算),或者时间戳包含任何无效的格式字符或尾随字符,则ODBC时间戳验证失败。

空字符串(‘’)参数返回0(1840年12月31日)。NULL参数返回NULL

这个函数也可以从ObjectScript中使用DATE()方法调用来调用:

DHC-APP>  WRITE $SYSTEM.SQL.DATE("2018-02-23 12:37:45")
64702

$HOROLOG 与 $ZTIMESTAMP

$HOROLOG$ZTIMESTAMP返回字符串值。 当字符串被转换为数字类型时,它总是返回一个数字值0(0)。0的 IRIS DATE数据类型值是1840年12月31日

因此,为了将$HOROLOG$ZTIMESTAMP解释为当前日期,必须在它前面加上一个加号(+),这将强制进行数字解释。 如下示例所示:

SELECT DATE($HOROLOG),DATE($ZTIMESTAMP)  

image

SELECT DATE(+$HOROLOG),DATE(+$ZTIMESTAMP)  

image

ODBC日期字符串

DATE函数和$SYSTEM.SQL.DATE()方法都可以接受ODBC日期格式字符串。 它们验证输入字符串。 如果通过验证,则返回相应的日期。 如果验证失败,则返回0。 验证过程如下:

  • 必须对应于ODBC格式:yyyy-mm-dd hh:mm:ss.xx。 整个字符串将被解析以获得正确的格式,而不仅仅是字符串的日期部分。
  • 字符串必须包含(至少)完整的日期:yyyy-mm-dd。 前导零可以省略或包括。 时间部分为可选,可以包括yyyy-mm-dd hh:
  • 字符串的每个数字元素(包括日期部分和时间部分)都必须包含一个有效值。 例如,月的取值范围为1 ~ 12(包括1 ~ 12)。 日值不能超过指定月份的天数。 闰年的天数是计算出来的。
  • 日期必须在%Library.TimeStamp日期范围内。最小日期为0001-01-01,最大日期为9999-12-31

示例

以下示例采用数据类型%Library.TimeStamp的值:

/// d ##class(PHA.TEST.SQLCommand).Date()
ClassMethod Date()
{
	s myquery = "SELECT {fn NOW} AS NowCol,DATE({fn NOW}) AS DateCol"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	if qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
	s rset = tStatement.%Execute()
	d rset.%Display()
}

DHC-APP>d ##class(PHA.TEST.SQLCommand).Date()
NowCol  DateCol
2022-02-02 10:29:48     66142
 
1 Rows(s) Affected
ClassMethod Date1()
{
	s myquery = "SELECT CURRENT_TIMESTAMP AS TSCol,DATE(CURRENT_TIMESTAMP) AS DateCol"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	s rset = tStatement.%Execute()
	d rset.%Display()
}
DHC-APP> d ##class(PHA.TEST.SQLCommand).Date1()
TSCol   DateCol
2022-02-02 10:30:40     66142
 
1 Rows(s) Affected
/// d ##class(PHA.TEST.SQLCommand).Date2()
ClassMethod Date2()
{
	s myquery = "SELECT GETDATE() AS GetDateCol,DATE(GETDATE()) AS DateCol"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	s rset = tStatement.%Execute()
	d rset.%Display()
}
DHC-APP>d ##class(PHA.TEST.SQLCommand).Date2()
GetDateCol      DateCol
2022-02-02 10:31:31     66142
 
1 Rows(s) Affected

下面的示例采用%Library.TimeStamp格式的字符串值:

ClassMethod Date3()
{
	s myquery = "SELECT '2018-02-22 13:14:23' AS DateStrCol,DATE('2018-02-22 13:14:23') AS DateCol"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	s rset = tStatement.%Execute()
	d rset.%Display()
}
DHC-APP>d ##class(PHA.TEST.SQLCommand).Date3()
DateStrCol      DateCol
2018-02-22 13:14:23     64701
 
1 Rows(s) Affected

以下示例采用以 IRIS逻辑格式表示日期的字符串值。为了将这些值正确转换为%Library.Date数据类型,该值必须以加号(+)为前缀,以强制进行数值计算:

ClassMethod Date4()
{
	s myquery = "SELECT $H AS HoroCol,DATE(+$H) AS DateCol"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	s rset = tStatement.%Execute()
	d rset.%Display()
}
DHC-APP> d ##class(PHA.TEST.SQLCommand).Date4()
HoroCol DateCol
66142,38015     66142
 
1 Rows(s) Affected
/// d ##class(PHA.TEST.SQLCommand).Date5()
ClassMethod Date5()
{
	s myquery = "SELECT $ZTIMESTAMP AS TSCol,DATE(+$ZTIMESTAMP) AS DateCol"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	s rset = tStatement.%Execute()
	d rset.%Display()
}
DHC-APP>d ##class(PHA.TEST.SQLCommand).Date5()
TSCol   DateCol
66142,9262.279  66142
 
1 Rows(s) Affected
0
0 111
文章 姚 鑫 · 一月 31, 2022 1m read

第四十章 SQL函数 DATALENGTH

返回表达式中字符数的函数。

大纲

DATALENGTH(expression)

参数

  • expression - 表达式,可以是列的名称、字符串字面值或另一个标量函数的结果。 基础数据类型可以是字符类型(如CHARVARCHAR)、数字或数据流。

DATALENGTH返回INTEGER数据类型。

描述

注意:DATALENGTHCHAR_LENGTHCHARACTER_LENGTH函数是相同的。 对于新代码,建议使用CHAR_LENGTH函数。 DATALENGTH是为TSQL兼容性而提供的。

0
0 87
文章 姚 鑫 · 一月 30, 2022 1m read

第三十九章 SQL函数 DATABASE

返回数据库名称限定符的标量字符串函数。

大纲

{fn DATABASE()}

描述

DATABASE返回与连接句柄对应的数据库名称的当前限定符。 在IRIS中,DATABASE总是返回空字符串(")。

0
0 133
文章 姚 鑫 · 一月 29, 2022 2m read

第三十八章 SQL函数 CURTIME

返回当前本地时间的标量日期/时间函数。

大纲

{fn CURTIME()}
{fn CURTIME}

描述

``不接受任何参数。它将当前本地时间作为数据类型TIME返回。请注意,参数括号是可选的。CURTIME返回此时区的当前本地时间;它根据本地时间变量(如夏令时)进行调整。

逻辑模式下的CURTIME$HOROLOG格式返回当前本地时间; 例如,37065年。 显示模式下的CURTIME以区域设置的默认格式返回当前本地时间; 例如,10:18:27

小时以24小时格式表示。

要更改默认的时间格式,使用SET OPTION命令和TIME_FORMATTIME_PRECISION选项。

要只返回当前时间,请使用CURTIMECURRENT_TIME。 这些函数以TIME数据类型返回它们的值。 CURRENT_TIMESTAMPGETDATENOW函数也可以作为TIMESTAMP数据类型返回当前日期和时间。

请注意,除了GETUTCDATE之外,所有 SQL时间和日期函数都特定于当地时区设置。 要获得通用的(独立于时区的)当前时间戳,你可以使用GETUTCDATE或ObjectScript $ZTIMESTAMP特殊变量。

在使用嵌入式SQL时,这些数据类型的性能不同。 TIME数据类型将值存储为$HOROLOG格式的整数(从午夜开始的秒数); 在SQL中显示时,转换为时间显示格式; 当从嵌入式SQL返回时,它们作为整数返回。 TIMESTAMP数据类型以相同的格式存储和显示其值。 可以使用CASTCONVERT函数来更改时间和日期的数据类型。

示例

下面的例子都返回当前系统时间:

SELECT {fn CURTIME()} AS TimeNow

9:27:30
SELECT {fn CURTIME} AS TimeNow

9:27:42

下面的嵌入式SQL示例返回当前时间。 因为这个时间是以$HOROLOG格式存储的,所以它被返回为一个整数:

  &sql(SELECT {fn CURTIME} INTO :a)
  IF SQLCODE'=0 {
    WRITE !,"Error code ",SQLCODE }
  ELSE {
    WRITE !,"Current time is: ",a }

下面的例子将Contacts表中选中行的LastCall字段设置为当前系统时间:

UPDATE Contacts Set LastCall = {fn CURTIME()}
  WHERE Contacts.ItemNumber=:item
0
0 64
文章 姚 鑫 · 一月 28, 2022 6m read

第三十七章 SQL函数 CURRENT_TIMESTAMP

日期/时间函数,返回当前本地日期和时间。

大纲

CURRENT_TIMESTAMP
CURRENT_TIMESTAMP(precision)

参数

  • precision - 一个正整数,它将时间精度指定为小数秒的位数。 默认值是0(没有小数秒); 这个默认值是可配置的。

CURRENT_TIMESTAMP返回TIMESTAMP数据类型。

描述

CURRENT_TIMESTAMP要么不接受参数,要么接受精度参数。 不允许使用空参数括号。

CURRENT_TIMESTAMP返回当前时区的本地日期和时间; 它会根据当地的时间变化进行调整,例如日光节约时间。

CURRENT_TIMESTAMP可以返回%timestamp数据类型格式(yyyy-mm-dd hh:mm:ss.ffff)%PosixTime数据类型格式(编码的64位带符号整数)的时间戳。 以下规则决定返回哪种时间戳格式:

  1. 如果将当前时间戳提供给数据类型为%PosixTime的字段,则当前时间戳值将以PosixTime数据类型格式返回。 例如,WHERE PosixField=CURRENT_TIMESTAMP or INSERT INTO MyTable (PosixField) VALUES (CURRENT_TIMESTAMP).

  2. 如果将当前的时间戳提供给数据类型为%timestamp的字段,则以timestamp数据类型格式返回当前的时间戳值。 例如WHERE TSField=CURRENT_TIMESTAMP or INSERT INTO MyTable (TSField) VALUES (CURRENT_TIMESTAMP).

  3. 如果没有上下文提供当前时间戳,则以timestamp数据类型格式返回当前时间戳值。 例如:SELECT CURRENT_TIMESTAMP

可以使用$HOROLOG以内部格式存储或返回当前本地日期和时间。

要更改默认的datetime字符串格式,使用SET OPTION命令和各种日期和时间选项。

当使用CREATE TABLEALTER TABLE定义datetime字段时,可以指定CURRENT_TIMESTAMP(带精度或不带精度)作为字段的默认值。 CURRENT_TIMESTAMP可以被指定为数据类型为%Library的字段的默认值。 PosixTime%Library.TimeStamp; 当前日期和时间以字段的数据类型指定的格式存储。

精确到小数部分的秒

CURRENT_TIMESTAMP有两种语法形式:

  • 如果没有参数括号,CURRENT_TIMESTAMP在功能上与NOW相同。 它使用系统范围内的默认时间精度。
  • 带有圆括号的参数CURRENT_TIMESTAMP(precision)在功能上与GETDATE相同,除了CURRENT_TIMESTAMP()精度参数是强制性的。 CURRENT_TIMESTAMP()总是返回指定的精度,并忽略配置的系统范围内的缺省时间精度。

分数秒总是被截断,而不是四舍五入到指定的精度。

  • TIMESTAMP数据类型格式中,精度的最大可能数字是9。 实际支持的数字数由precision参数、配置的默认时间精度和系统能力决定。 如果指定的精度大于配置的默认时间精度,则精度的其他数字将作为尾随零返回。
  • POSIXTIME数据类型格式中,精度的最大可能数字为6。 每个POSIXTIME值使用6位精度计算; 除非提供,否则这些小数数字默认为零。 实际支持的非零位数由precision参数、配置的缺省时间精度和系统能力决定。

配置精度

默认精度可以通过以下方式配置:

  • 使用TIME_PRECISION选项设置OPTION
  • 系统范围的$SYSTEM.SQL.Util.SetOption()方法配置选项DefaultTimePrecision。 要确定当前设置,调用$SYSTEM.SQL.CurrentSettings(),它显示默认的时间精度; 默认值为0。
  • 进入管理门户,选择“系统管理”、“配置”、“SQL和对象设置”、“SQL”。 查看和编辑GETDATE()CURRENT_TIMECURRENT_TIMESTAMP的默认时间精度的当前设置。

指定从09(包括9)的整数,作为返回的十进制精度的默认位数。 默认值为0。 实际返回的精度取决于平台; 超过系统中可用精度的精度数字将作为零返回。

日期和时间函数比较

GETDATENOW也可用于返回当前本地日期和时间,作为TIMESTAMP数据类型或POSIXTIME数据类型值。 GETDATE支持精度,NOW不支持精度。

SYSDATECURRENT_TIMESTAMP相同,只是SYSDATE不支持精度。 CURRENT_TIMESTAMP是首选的SQL函数; 提供SYSDATE是为了与其他厂商兼容。

GETUTCDATE可以作为TIMESTAMP数据类型或POSIXTIME数据类型值返回通用的(与时区无关的)日期和时间。 请注意,除了GETUTCDATE之外,所有 SQL时间和日期函数都特定于当地时区设置。 要获得一个通用的(独立于时区的)时间戳,你可以使用GETUTCDATE或者ObjectScript $ZTIMESTAMP特殊变量。

要只返回当前本地日期,请使用CURDATECURRENT_DATE。 要只返回当前本地时间,请使用CURRENT_TIMECURTIME。 这些函数返回DATETIME数据类型的值。 这些函数都不支持精度。

TIMESTAMP数据类型的存储格式和显示格式是相同的。 POSIXTIME数据类型存储格式是一个编码的64位有符号整数。 TIMEDATE数据类型将它们的值存储为$HOROLOG格式的整数; 当在SQL中显示时,它们被转换为日期或时间显示格式。 默认情况下,嵌入式SQL以逻辑(存储)格式返回。

可以使用CASTCONVERT函数来更改日期和时间的数据类型。

示例

下面的例子以三种不同的方式返回当前本地日期和时间:TIMESTAMP数据类型格式,具有系统默认时间精度,具有两位小数秒的精度,以及$HOROLOG内部存储格式,具有全秒:

SELECT 
   CURRENT_TIMESTAMP AS FullSecStamp,
   CURRENT_TIMESTAMP(2) AS FracSecStamp,
   $HOROLOG AS InternalFullSec

下面的嵌入式SQL示例设置了区域设置的缺省时间精度。 第一个CURRENT_TIMESTAMP没有指定精度; 它返回带有默认时间精度的当前时间。 第二个CURRENT_TIMESTAMP指定精度; 这将覆盖配置的缺省时间精度。 precision参数可以大于或小于默认的时间精度设置:

ClassMethod CurrentTimestamp()
{
InitialVal
	s pre = ##class(%SYS.NLS.Format).GetFormatItem("TimePrecision")
ChangeVal
	s x = ##class(%SYS.NLS.Format).SetFormatItem("TimePrecision",4)
	&sql(SELECT CURRENT_TIMESTAMP,CURRENT_TIMESTAMP(2) INTO :a,:b)
	if SQLCODE'=0 {
		w !,"Error code ",SQLCODE }
	else {
	w !,"Timestamp is:  ",a
	w !,"Timestamp is:  ",b }
RestoreVal
	s x = ##class(%SYS.NLS.Format).SetFormatItem("$TimePrecision",pre)
}
DHC-APP>d ##class(PHA.TEST.SQLCommand).CurrentTimestamp()
 
Timestamp is:  2022-01-25 09:22:49
Timestamp is:  2022-01-25 09:22:49.49

下面的嵌入式SQL示例比较了本地(特定时区)和通用(独立时区)的时间戳:

ClassMethod CurrentTimestamp1()
{
	&sql(SELECT CURRENT_TIMESTAMP,GETUTCDATE() INTO :a,:b)
	IF SQLCODE'=0 {
		w !,"Error code ",SQLCODE }
	ELSE {
		w !,"Local timestamp is:  ",a
		w !,"UTC timestamp is:    ",b
		w !,"$ZTIMESTAMP is:      ",$ZDATETIME($ZTIMESTAMP,3,,3)
 }
DHC-APP>d ##class(PHA.TEST.SQLCommand).CurrentTimestamp1()
 
Local timestamp is:  2022-01-25 09:23:58
UTC timestamp is:    2022-01-25 01:23:58
$ZTIMESTAMP is:      2022-01-25 01:23:58.568

下面的示例将Orders表中所选行中的LastUpdate字段设置为当前系统日期和时间。 如果LastUpdate是数据类型%TimeStamp, CURRENT_TIMESTAMP将返回当前日期和时间作为ODBC时间戳; 如果LastUpdate是数据类型%PosixTime, CURRENT_TIMESTAMP返回当前日期和时间为编码的64位有符号整数:

UPDATE Orders SET LastUpdate = CURRENT_TIMESTAMP
  WHERE Orders.OrderNumber=:ord

下面的例子创建了一个名为Orders的表,记录收到的产品订单:

CREATE TABLE Orders (
     OrderId     INT NOT NULL,
     ClientId    INT,
     ItemName    CHAR(40) NOT NULL,
     OrderDate   TIMESTAMP DEFAULT CURRENT_TIMESTAMP(3),
     PRIMARY KEY (OrderId))

OrderDate列包含收到订单的日期和时间。 它使用TIMESTAMP数据类型,并使用精度为3的CURRENT_TIMESTAMP函数插入当前系统日期和时间作为默认值。

0
0 485
文章 姚 鑫 · 一月 28, 2022 3m read

第三十六章 SQL函数 CURRENT_TIME

返回当前本地时间的日期/时间函数。

大纲

CURRENT_TIME
CURRENT_TIME(precision)

参数

  • precision - 一个正整数,它将时间精度指定为小数位数。默认值为0(无小数秒);此默认值是可配置的。

CURRENT_TIME返回时间数据类型。

描述

CURRENT_TIME要么不带参数,要么带精度参数。不允许使用空参数括号。

CURRENT_TIME返回此时区的当前本地时间。它会根据当地时间变化(如夏令时)进行调整。

逻辑模式下的CURRENT_TIME$HOROLOG格式返回当前本地时间;例如,37065。显示模式下的当前时间以区域设置的默认格式返回当前本地时间;例如,10:18:27

要更改默认时间格式,请使用带有time_formattime_PRECISION选项的SET OPTION命令。可以配置分数秒的精度,如下所述。

要仅返回当前时间,请使用CURRENT_TIMECURTIME。这些函数以时间数据类型返回它们的值。CURRENT_TIMESTAMPGETDATENOW函数也可用于将当前日期和时间作为TIMESTAMP数据类型返回。

请注意,除GETUTCDATE之外,所有 SQL时间和日期函数都特定于本地时区设置。要获得通用的当前时间戳(独立于时区),可以使用GETUTCDATEObjectScript $ZTIMESTAMP特殊变量。

使用嵌入式SQL时,这些数据类型的执行方式不同。时间数据类型以$HOROLOG格式将值存储为整数(作为自午夜以来的秒数);以SQL显示时,它们将转换为时间显示格式;从嵌入式SQL返回时,它们将作为整数返回。时间戳数据类型存储并以相同格式显示其值。可以使用CAST或转换功能来更改时间和日期的数据类型。

CURRENT_TIME可以用作CREATE TABLEALTER TABLE中的默认规范关键字。CURRENT_TIME用作默认规范关键字时不能指定精度参数。

小数秒精度

当前的时间可以返回高达9位数的分数秒精度。精度位数的默认值可以使用以下配置:

  • 使用TIME_PRECISION选项设置选项。
  • 系统范围的$SYSTEM.SQL.Util.SetOption()方法配置选项DefaultTimePrecision。 要确定当前设置,调用$SYSTEM.SQL.CurrentSettings(),它显示默认的时间精度; 默认值为0。
  • 进入管理门户,选择“系统管理”、“配置”、“SQL和对象设置”、“SQL”。 查看和编辑GETDATE()CURRENT_TIMECURRENT_TIMESTAMP的默认时间精度的当前设置。

指定从09(包括9)的整数,作为返回的十进制精度的默认位数。 默认值为0。 实际返回的精度取决于平台; 超过系统中可用精度的数字将作为零返回。

示例

以下示例返回当前系统时间:

SELECT CURRENT_TIME

9:10:27

下面的示例返回的是当前系统时间,精度为3位小数秒:

SELECT CURRENT_TIME(3)

9:10:34

下面的嵌入式SQL示例返回当前时间。 因为这个时间是以$HOROLOG格式存储的,所以它被返回为一个整数:

ClassMethod CurrentTime()
{
  &sql(SELECT CURRENT_TIME INTO :a)
  IF SQLCODE'=0 {
    WRITE !,"Error code ",SQLCODE }
  ELSE {
    WRITE !,"Current time is: ",a }
}
    
    
DHC-APP> d ##class(PHA.TEST.SQLCommand).CurrentTime()
 
Current time is: 33104

下面的例子将Contacts表中选中行的LastCall字段设置为当前系统时间:

UPDATE Contacts SET LastCall = CURRENT_TIME
  WHERE Contacts.ItemNumber=:item
0
0 99
文章 姚 鑫 · 一月 26, 2022 2m read

第三十五章 SQL函数 CURRENT_DATE

日期/时间函数,返回当前本地日期。

大纲

CURRENT_DATE

描述

CURRENT_DATE不带任何参数。它将当前本地日期作为数据类型DATE返回。不允许使用参数括号。CURRENT_DATE返回此时区的当前本地日期;它根据本地时间变量(如夏令时)进行调整。

在逻辑模式下CURRENT_DATE$HOROLOG格式返回当前本地日期; 例如,64701。 显示模式下的CURRENT_DATE以区域设置的默认格式返回当前本地日期。 例如,在美国的区域设置为02/22/2018,在欧洲的区域设置为22/02/2018,在俄罗斯的区域设置为22.02.2018

要指定不同的日期格式,请使用TO_DATE函数。要更改默认日期格式,请将SET OPTION命令与DATE_FORMATYear_OPTIONDATE_SEFACTOR选项配合使用。

要仅返回当前日期,请使用CURRENT_DATECURDATE。这些函数以DATE数据类型返回它们的值。CURRENT_TIMESTAMPGETDATENOW函数也可用于将当前日期和时间作为TIMESTAMP数据类型返回。

请注意,除GETUTCDATE之外,所有 SQL时间和日期函数都特定于本地时区设置。要获得通用的当前时间戳(独立于时区),可以使用GETUTCDATE或ObjectScript $ZTIMESTAMP特殊变量。

使用嵌入式SQL时,这些数据类型的执行方式不同。DATE数据类型将值存储为$HOROLOG格式的整数;当在SQL中显示时,它们将转换为日期显示格式;当从嵌入式SQL返回时,它们将作为整数返回。TIMESTAMP数据类型以相同的格式存储和显示其值。可以使用CONVERT函数更改日期和时间的数据类型。

CURRENT_DATE可以用作CREATE TABLEALTER TABLE中的默认规范关键字。

示例

下面的示例返回转换为显示模式的当前日期:

SELECT CURRENT_DATE AS Today

2022/1/24 0:00:00

下面的嵌入式SQL示例返回存储的当前日期。由于此日期以$HOROLOG格式存储,因此将以整数形式返回:

  &sql(SELECT CURRENT_DATE INTO :a)
   IF SQLCODE'=0 {
     WRITE !,"Error code ",SQLCODE }
   ELSE {
     WRITE !,"Current date is: ",a }
DHC-APP>d ##class(PHA.TEST.SQLCommand).CurrentDate()
 
Current date is: 66133
DHC-APP>

以下示例显示如何在WHERE子句中使用CURRENT_DATE返回最近1000天内出生的人的记录:

SELECT Name,DOB,Age
FROM Sample.Person
WHERE DOB > CURRENT_DATE - 1000
0
0 303
文章 姚 鑫 · 一月 25, 2022 2m read

第三十四章 SQL函数 CURDATE

返回当前本地日期的标量日期/时间函数。

大纲

{fn CURDATE()}
{fn CURDATE}

描述

CURDATE不接受任何参数。它将当前本地日期作为数据类型DATE返回。请注意,参数括号是可选的。CURDATE返回此时区的当前本地日期;它根据本地时间变量(如夏令时)进行调整。

逻辑模式下的CURDATE$HOROLOG格式返回当前本地日期; 例如,64701。 显示模式下的CURDATE以区域设置的默认格式返回当前本地日期。 例如,在美国的区域设置为02/22/2018,在欧洲的区域设置为22/02/2018,在俄罗斯的区域设置为22.02.2018

要指定不同的日期格式,请使用TO_DATE函数。 要更改默认的日期格式,使用SET OPTION命令和DATE_FORMATYEAR_OPTIONDATE_SEPARATOR选项。

要只返回当前日期,请使用CURDATECURRENT_DATE。 这些函数返回DATE数据类型的值。 CURRENT_TIMESTAMPGETDATENOW函数也可以作为TIMESTAMP数据类型返回当前日期和时间。

请注意,除了GETUTCDATE之外,所有 SQL时间和日期函数都特定于当地时区设置。 要获得通用的(独立于时区的)当前时间戳,你可以使用GETUTCDATE或ObjectScript $ZTIMESTAMP特殊变量。

在使用嵌入式SQL时,这些数据类型的性能不同。 DATE数据类型将值存储为$HOROLOG格式的整数; 当在SQL中显示时,它们被转换为日期显示格式; 当从嵌入式SQL返回时,它们作为整数返回。 TIMESTAMP数据类型以相同的格式存储和显示其值。 可以使用CONVERT函数来更改日期和时间的数据类型。

示例

下面的例子都返回当前日期:

SELECT {fn CURDATE()} AS Today

2022/1/24 0:00:00
SELECT {fn CURDATE} AS Today

2022/1/24 0:00:00

下面的嵌入式SQL示例返回当前日期。 因为这个日期是以$HOROLOG格式存储的,所以它被返回为一个整数:

  &sql(SELECT {fn CURDATE()} INTO :a)
  WRITE !,"Current date is: ",a
DHC-APP>d ##class(PHA.TEST.SQLCommand).CurDate()
 
Current date is: 66133

下面的例子展示了如何在SELECT语句中使用CURDATE返回所有发货日期相同或晚于今天日期的记录:

SELECT * FROM Orders 
     WHERE ShipDate >= {fn CURDATE()}
0
0 92
文章 姚 鑫 · 一月 24, 2022 1m read

第三十三章 SQL函数 COT

标量数值函数,返回角度的余切值(以弧度为单位)。

大纲

{fn COT(numeric-expression)}

参数

  • numeric-expression - 数值表达式。 这是一个用弧度表示的角。

COT返回NUMERICDOUBLE数据类型。 如果数值表达式是数据类型DOUBLE, COT返回DOUBLE; 否则,返回NUMERIC

描述

COT接受任何非零数,并以浮点数的形式返回它的余切值。 如果传入NULL值,COT将返回NULL。 数值0(0)会导致运行时错误,生成SQLCODE -400(发生致命错误)。 COT将非数字字符串视为数值0

COT返回一个精度为36、刻度为18的值。

COT只能用作ODBC标量函数(使用花括号语法)。

可以使用DEGREES函数将弧度转换为角度。 可以使用RADIANS函数来转换角度到弧度。

示例

下面的例子展示了COT的效果:

SELECT {fn COT(0.52)} AS Cotangent 

1.746536264145397165
SELECT {fn COT(124.1332)} AS Cotangent 

-0.040311998371146672
0
0 100
文章 姚 鑫 · 一月 23, 2022 1m read

第三十二章 SQL函数 COS

标量数值函数,返回一个角的余弦值(以弧度为单位)。

大纲

{fn COS(numeric-expression)}

参数

  • numeric-expression - 数值表达式。 这是一个用弧度表示的角。

COS返回NUMERICDOUBLE数据类型。 如果数值表达式是数据类型DOUBLE, COS返回DOUBLE; 否则,返回NUMERIC

描述

COS接受任何数值,并以浮点数的形式返回COS。 返回值的范围是-11(含1)。 如果传入NULL值,COS将返回NULLCOS将非数字字符串视为数值0

COS返回一个精度为19、刻度为18的值。

COS只能用作ODBC标量函数(使用花括号语法)。

可以使用DEGREES函数将弧度转换为角度。 可以使用RADIANS函数来转换角度到弧度。

示例

这些例子说明了COS对两个正弦函数的影响。

SELECT {fn COS(0.52)} AS Cosine

0.8678191796776499
SELECT {fn COS(-.31)} AS Cosine 

SELECT {fn COS(-.31)} AS Cosine 
0
0 61
文章 姚 鑫 · 一月 22, 2022 8m read

第三十一章 SQL函数 CONVERT

将给定表达式转换为指定数据类型的函数。

CONVERT(datatype,expression[,format-code])

{fn CONVERT(expression,datatype)}

参数

  • expression - 要转换的表达式。
  • datatype - 要将表达式转换为的数据类型。
  • format - 可选-指定日期和时间格式的整数代码,用于在日期/时间/时间戳数据类型和字符数据类型之间进行转换。 此参数仅用于通用标量语法形式。

描述

这里描述了CONVERT函数的两种不同实现。 两者都将一种数据类型中的表达式转换为另一种数据类型中的相应值。 两者都执行日期和时间转换。

注意:这两个CONVERT实现中的参数以不同的顺序表示。 第一个是与MS SQL Server兼容的通用 IRIS标量函数,它接受三个参数。 第二个是带有两个参数的 ODBC标量函数。 下面的文本将分别处理这两种形式的CONVERT

  • CONVERT(datatype,expression)支持流数据的转换。 例如,可以将字符流字段的内容转换为数据类型为VARCHAR的字符串。
  • {fn CONVERT(expression,datatype)}不支持流数据的转换; 指定要表达的流字段将导致SQLCODE -37错误。

为两个版本的CONVERT指定一个无效值将导致SQLCODE -141

如果表达式没有定义的数据类型(例如ObjectScript提供的主机变量),则其数据类型默认为字符串数据类型。

CONVERT(datatype,expression,format-code)

可以通过执行VARCHAR-to-VARCHAR转换来截断字符串,指定输出字符串长度小于表达式字符串长度。

在使用CONVERT(或CAST)时,如果字符数据类型(如CHARVARCHAR)没有指定长度,则默认的最大长度为30个字符。 如果二进制数据类型(如binaryVARBINARY)没有指定长度,则默认的最大长度为30个字符。 否则,这些没有指定长度的数据类型将被映射到一个1个字符的MAXLEN,如data types表所示。

可以执行BIT数据类型转换。 允许的值为10NULL。 如果指定任何其他值,IRIS将发出SQLCODE -141错误。 在下面的嵌入式SQL示例中,两者都是一个NULLBIT转换:

ClassMethod Convert()
{
	s a=""
	&sql(
		SELECT CONVERT(BIT,:a),
			CONVERT(BIT,NULL)
		INTO :x,:y)
	w !,"SQLCODE=",SQLCODE
	w !,"the host variable is:",x
	w !,"the NULL keyword is:",y
}

可选的format-code参数指定日期、datetime或时间格式。 该格式既可用于定义从日期/时间/时间戳数据类型转换为字符串时的输出,也可用于定义从字符串转换为日期/时间/时间戳数据类型时的输入。 支持以下格式代码; 输出两位数年份的格式代码列在第一列; 输出四位数年或不输出年的格式列在第二列:

Two-digit year codesFour-digit year codesFormat
 0 or 100Mon dd yyyy hh:mmAM (or PM)
1101mm/dd/yy
2102yy.dd.mm
3103dd/mm/yy
4104dd.mm.yy
5105dd-mm-yy
6106dd Mon yy
7107Mon dd, yy (no leading zero when dd < 10)
 8 or 108hh:mm:ss
 9 or 109Mon dd yyyy hh:mm:ss:nnnAM (or PM)
10110mm-dd-yy
11111yy.mm.dd
12112yymmdd
 13 or 113dd Mon yyyy hh:mm:ss:nnn (24 hour)
 14 or 114hh:mm:ss.nnn (24 hour)
 20 or 120yyyy-mm-dd hh:mm:ss (24 hour)
 21 or 121yyyy-mm-dd hh:mm:ss.nnnn (24 hour)
 126yyyy-mm-ddThh:mm:ss,nnnn (24 hour)
 130dd Mon yyyy hh:mm:ss:nnnAM (or PM)
 131dd/mm/yyyy hh:mm:ss:nnnAM (or PM)

以下是日期和时间转换的特性:

  • 取值范围:允许的日期范围为0001-01-01 ~ 9999-12-31
  • 默认值:
    • 将时间值转换为TIMESTAMPPOSIXTIMEDATETIMESMALLDATETIME时,日期默认为1900-01-01。 注意,对于{fn CONVERT()},日期默认为1841-01-01
    • 将日期值转换为TIMESTAMPPOSIXTIMEDATETIMESMALLDATETIME时,时间默认为00:00:00
  • Default Format:如果没有指定Format -code, CONVERT将尝试从指定的值确定格式。 如果不能,则默认为格式代码100
  • 两位数年份:从00到49的两位数年份转换为21世纪的日期(2000到2049); 从50到99的两位数年份转换为20世纪的日期(1950到1999)。
  • 分数秒:分数秒前可以加句号(.)或冒号(:)。 这些符号有不同的含义:
    • 句点是默认值,可用于所有格式代码。 句号表示标准分数; 因此,12:00:00.4表示十分之四秒,而12:00:00.004表示千分之四秒。 分数精度的位数没有限制。
    • 冒号只能用于以下格式代码值:9/10913/11314/114130和131。 冒号表示后面的数字是千分之一秒; 因此12:00:00:4表示四万分之一秒(12:00:00.004)。 冒号后面的数字限制为3位。

当指定表达式的格式无效或格式与格式代码不匹配时,将产生SQLCODE -141错误。 指定一个不存在的格式代码将返回1900-01-01 00:00:00

{fn CONVERT(expression,datatype)}

这是ODBC标量函数。 它支持以下ODBC显式数据类型转换。 必须使用“SQL_”关键字指定这种形式的CONVERT的数据类型转换。 在下表中,有两组转换数据类型,第一组转换数据值和数据类型,第二组转换数据类型,但不转换数据值:

SourceConversion
Any numeric data typeSQL_VARCHAR, SQL_DOUBLE, SQL_DATE, SQL_TIME
%StringSQL_DATE, SQL_TIME, SQL_TIMESTAMP
%DateSQL_VARCHAR, SQL_POSIXTIME, SQL_TIMESTAMPSQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT, SQL_DATE
%TimeSQL_VARCHAR, SQL_POSIXTIME, SQL_TIMESTAMP SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT,SQL_SMALLINT, SQL_TINYINT, SQL_TIME
%PosixTimeSQL_TIMESTAMP, SQL_DATE, SQL_TIME SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
%TimeStampSQL_POSIXTIME, SQL_DATE, SQL_TIME SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
Any non-stream data typeSQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
Any non-stream data typeSQL_DOUBLE

SQL_VARCHAR是标准的ODBC表示。 在转换为SQL_VARCHAR时,日期和时间被转换为相应的ODBC表示; 数字数据类型值转换为字符串表示。 从SQL_VARCHAR转换时,该值必须是有效的ODBC TimeTimestampDate表示。

  • 当将时间值转换为SQL_TIMESTAMPSQL_POSIXTIME时,未指定的日期默认为1841-01-01。 注意,对于CONVERT(),日期默认为1900-01-01
  • date值转换为SQL_TIMESTAMPSQL_POSIXTIME时,时间默认为00:00:00

在这种语法形式中,小数秒前面可以加句号(.)或冒号(:)。 这些符号有不同的含义。 句号表示标准分数; 因此,12:00:00.4表示十分之四秒,而12:00:00.004表示千分之四秒。 冒号表示接下来的是千分之一秒; 因此12:00:00:4表示千分之四秒。 冒号后面的数字限制为3位。

在转换为整数数据类型或SQL_DOUBLE数据类型时,数据值(包括日期和时间)将转换为数字表示。 对于SQL_DATE,这是自1841年1月1日以来的天数。 对于SQL_TIME,这是自午夜以来的秒数。 当遇到非数字字符时,输入字符串将被截断。 整数数据类型还截断十进制数字,返回数字的整数部分。

{fn CONVERT(expression,datatype)}不支持流数据的转换; 指定要表达的流字段将导致SQLCODE -37错误。

转换成任何数据类型的NULL仍然是NULL

空字符串("),或任何非数字字符串值转换如下:

  • SQL_VARCHARSQL_TIMESTAMP返回提供的值。
  • 数字数据类型转换为0(零)。
  • SQL_DATESQL_TIME转换为NULL

CONVERT 类方法

还可以使用CONVERT()方法调用执行数据类型转换,使用" SQL_ "关键字指定数据类型:

$SYSTEM.SQL.Functions.CONVERT(expression,convert-to-type,convert-from-type)

如下示例所示:

 WRITE $SYSTEM.SQL.CONVERT(60945,"SQL_VARCHAR","SQL_DATE")
2007-11-11

示例

CONVERT() 示例

下面的示例使用标量语法形式的CONVERT

下面的示例比较了使用DECIMALDOUBLE数据类型对小数的转换:

SELECT CONVERT(DECIMAL,-123456789.0000123456789) AS DecimalVal,
       CONVERT(DOUBLE,-123456789.0000123456789) AS DoubleVal

下面的示例将字符流字段转换为VARCHAR文本字符串。 它还使用CHAR_LENGTH显示字符流字段的长度:

SELECT Notes,CONVERT(VARCHAR(80),Notes) AS NoteText,CHAR_LENGTH(Notes) AS TextLen
FROM Sample.Employee WHERE Notes IS NOT NULL

下面的例子展示了几种将出生日期字段(DOB)转换为格式化字符串的方法:

SELECT DOB,
       CONVERT(VARCHAR(20),DOB) AS DOBDefault,
       CONVERT(VARCHAR(20),DOB,100) AS DOB100,
       CONVERT(VARCHAR(20),DOB,107) AS DOB107,
       CONVERT(VARCHAR(20),DOB,114) AS DOB114,
       CONVERT(VARCHAR(20),DOB,126) AS DOB126
FROM Sample.Person

默认格式和代码100格式是相同的。 因为DOB字段不包含时间值,所以显示时间的格式(这里包括默认值100、114126)提供一个零值,它表示12:00AM(午夜)。 代码126格式提供了一个不包含空格的日期和时间字符串。

{fn CONVERT()} 示例

下面的示例使用了ODBC语法形式的CONVERT

下面的嵌入式SQL示例将混合字符串转换为整数。 IRIS在第一个非数字字符处截断字符串,然后将结果数字转换为规范形式:

ClassMethod Convert1()
{
	s a="007 James Bond"
	&sql(SELECT {fn CONVERT(:a, SQL_INTEGER)} INTO :x)
	w !,"SQLCODE=",SQLCODE
	w !,"the host variable is:",x
}

DHC-APP>d ##class(PHA.TEST.SQLCommand).Convert1()
 
SQLCODE=0
the host variable is:7

下面的示例将“DOB”(出生日期)列中的日期转换为SQL_TIMESTAMP数据类型。

SELECT DOB,{fn CONVERT(DOB,SQL_TIMESTAMP)} AS DOBtoTstamp
     FROM Sample.Person

生成的时间戳格式为“yyyy-mm-dd hh:mm:ss”

下面的示例将“DOB”(出生日期)列中的日期转换为SQL_INTEGER数据类型。

SELECT DOB,{fn CONVERT(DOB,SQL_INTEGER)} AS DOBtoInt
     FROM Sample.Person

下面的示例将“DOB”(出生日期)列中的日期转换为SQL_VARCHAR数据类型。

SELECT DOB,{fn CONVERT(DOB,SQL_VARCHAR)} AS DOBtoVChar
     FROM Sample.Person

生成的字符串格式为:yyyy-mm-dd

0
0 151
文章 姚 鑫 · 一月 21, 2022 2m read

第三十章 SQL函数 CONCAT

标量字符串函数,它返回作为连接两个字符表达式的结果的字符串。

大纲

{fn CONCAT(string-expression1,string-expression2)}

参数

  • string-expression1, string-expression2 - 要连接的字符串表达式。表达式可以是列名、字符串文字、数字或另一个标量函数的结果,其中底层数据类型可以表示为任何字符类型(如CHARVARCHAR)。

描述

连接两个字符串以返回连接的字符串。可以使用连接运算符(||)执行完全相同的操作。

可以连接数字或数字字符串的任意组合;连接结果是一个数字字符串。SQL在连接之前将数字转换为规范形式(指数被扩展,前导零和尾随零被删除)。在连接之前,数字字符串不会转换为规范形式。

可以将前导空格或尾随空格连接到字符串。将空值连接到字符串会产生空值;这是行业范围内的SQL标准。

字符串函数还可用于将两个或多个表达式连接成单个字符串。

示例

以下示例连接Home_StateHome_City列以创建位置值。使用CONCAT函数和concatenate运算符显示两次连接:

SELECT {fn CONCAT(Home_State,Home_City)} AS LocationFunc,
Home_State||Home_City AS LocationOp
FROM Sample.Person

以下示例显示尝试连接字符串和空值时发生的情况:

SELECT {fn CONCAT(Home_State,NULL)} AS StrNull
FROM Sample.Person

下面的示例显示数字在连接之前转换为规范形式。要避免这种情况,可以将数字指定为字符串,如下所示:

SELECT {fn CONCAT(Home_State,0012.00E2)} AS StrNum,
{fn CONCAT(Home_State,'0012.00E2')} AS StrStrNum
FROM Sample.Person

以下示例显示将保留尾随空格:

SELECT CHAR_LENGTH({fn CONCAT(Home_State,'          ')}) AS StrSpace
FROM Sample.Person
0
0 215
文章 姚 鑫 · 一月 20, 2022 7m read

第二十九章 SQL函数 COALESCE

返回第一个非空表达式的值的函数。

大纲

COALESCE(expression,expression [,...])
  • expression - 要计算的一系列表达式。多个表达式被指定为逗号分隔的列表。此表达式列表限制为140个表达式。

描述

COALESSE函数按从左到右的顺序计算表达式列表,并返回第一个非空表达式的值。如果所有表达式的计算结果都为NULL,则返回NULL

字符串返回时保持不变;保留前导和尾随空格。数字以规范形式返回,去掉了前导零和尾随零。

返回值的数据类型

非数字表达式(如字符串或日期)必须都属于相同的数据类型,并返回该数据类型的值。指定数据类型不兼容的表达式会导致SQLCODE-378错误,并显示DataType不匹配错误消息。可以使用CAST函数将表达式转换为兼容的数据类型。

数值表达式可以是不同的数据类型。如果指定具有不同数据类型的数值表达式,则返回的数据类型是与所有可能的结果值最兼容的表达式数据类型,即具有最高数据类型优先级的数据类型。

文字值(字符串、数字或NULL)被视为数据类型VARCHAR。如果只指定两个表达式,则文字值与数值表达式兼容:如果第一个表达式是数值表达式,则返回其数据类型;如果第一个表达式是文字值,则返回VARCHAR数据类型。

比较NULL处理函数

下表显示了各种SQL比较函数。如果逻辑比较测试为True(AB相同),则每个函数返回一个值;如果逻辑比较测试为False(AB不同),则每个函数返回另一个值。这些函数允许执行空逻辑比较。不能在实际相等(或不相等)条件比较中指定NULL

SQL函数比较测试返回值
COALESCE(ex1,ex2,...)ex = NULL for each argumentTrue tests next ex argument. If all ex arguments are True (NULL), returns NULL. False returns ex
IFNULL(ex1,ex2) [two-argument form]ex1 = NULLTrue returns ex2 False returns NULL
IFNULL(ex1,ex2) [three-argument form]ex1 = NULLTrue returns ex2 False returns ex3
{fn IFNULL(ex1,ex2)}ex1 = NULLTrue returns ex2 False returns ex1
ISNULL(ex1,ex2)ex1 = NULLTrue returns ex2 False returns ex1
NVL(ex1,ex2)ex1 = NULLTrue returns ex2 False returns ex1
NULLIF(ex1,ex2)ex1 = ex2True returns NULL False returns ex1

示例

下面的嵌入式SQL示例接受一系列主机变量值,并返回第一个非空的(值d)。请注意,ObjectScript空字符串("")在 SQL中被转换为NULL

ClassMethod Coalesce()
{
	s (a, b, c, e) = ""
	s d = "firstdata"
	s f = "nextdata"
	&sql(SELECT COALESCE(:a,:b,:c,:d,:e,:f) INTO :x)
	if SQLCODE '= 0 {
		w !,"Error code ",SQLCODE 
	} else {
		w !,"The first non-null value is: ",x 
	}
}
DHC-APP>d ##class(PHA.TEST.SQLCommand).Coalesce()
 
The first non-null value is: firstdata

下面的示例按从左到右的顺序比较两列的值,并返回第一个非空列的值。对于某些行,FavoriteColors列为NULLHome_State列从不为NULL。为了让Coalesce将两者进行比较,FavoriteColors必须转换为字符串:

SELECT TOP 25 Name,FavoriteColors,Home_State,
COALESCE(CAST(FavoriteColors AS VARCHAR),Home_State) AS CoalesceCol
FROM Sample.Person

以下动态SQL示例将COALESCE与其他NULL处理函数进行比较:

ClassMethod Coalesce1()
{
	s myquery = "SELECT TOP 50 %ID,"_
	            "IFNULL(FavoriteColors,'blank') AS Ifn2Col,"_
	            "IFNULL(FavoriteColors,'blank','value') AS Ifn3Col,"_
	            "COALESCE(CAST(FavoriteColors AS VARCHAR),Home_State) AS CoalesceCol,"_
	            "ISNULL(FavoriteColors,'blank') AS IsnullCol,"_
	            "NULLIF(FavoriteColors,$LISTBUILD('Orange')) AS NullifCol,"_
	            "NVL(FavoriteColors,'blank') AS NvlCol"_
	            " FROM Sample.Person"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(myquery)
	if qStatus '= 1 {
		w "%Prepare failed:" 
		d $System.Status.DisplayError(qStatus) 
		q
	}
	s rset = tStatement.%Execute()
	d rset.%Display()
	w !,"End of data"
}
DHC-APP>d ##class(PHA.TEST.SQLCommand).Coalesce1()
ID      Ifn2Col Ifn3Col CoalesceCol     IsnullCol       NullifCol       NvlCol
1               value   $lb("Red","Orange","Yellow")    $lb("Red","Orange","Yellow")    $lb("Red","Orange","Yellow")    $lb("Red","Orange","Yellow")
2       blank   blank           blank           blank
6       blank   blank           blank           blank
9       blank   blank           blank           blank
10      blank   blank           blank           blank
13              value   $lb("Red","Orange","Yellow","Green")    $lb("Red","Orange","Yellow","Green")    $lb("Red","Orange","Yellow","Green")    $lb("Red","Orange","Yellow","Green")
14              value   ReOrangYellowGreen     $lb("Red","Orange","Yellow","Green","Green")    $lb("Red","Orange","Yellow","Green","Green")    $lb("Red","Orange","Yellow","Green","Green")
15              value   ReOrangYellowGreen     $lb("Red","Orange","Yellow","Green","Yellow")   $lb("Red","Orange","Yellow","Green","Yellow")   $lb("Red","Orange","Yellow","Green","Yellow")
16              value   $lb("White")    $lb("White")    $lb("White")    $lb("White")
17              value   $lb("Black")    $lb("Black")    $lb("Black")    $lb("Black")
18              value   $lb("Green","White")    $lb("Green","White")    $lb("Green","White")    $lb("Green","White")
19              value   $lb("Purple")   $lb("Purple")   $lb("Purple")   $lb("Purple")
20              value   $lb("Yellow")   $lb("Yellow")   $lb("Yellow")   $lb("Yellow")
21              value   $lb("Red","Red")        $lb("Red","Red")        $lb("Red","Red")        $lb("Red","Red")
22              value   $lb("Black","Black")    $lb("Black","Black")    $lb("Black","Black")    $lb("Black","Black")
23      blank   blank   MT      blank           blank
24              value   $lb("Blue")     $lb("Blue")     $lb("Blue")     $lb("Blue")
25      blank   blank   WY      blank           blank
26              value   $lb("White")    $lb("White")    $lb("White")    $lb("White")
27              value   $lb("Orange")   $lb("Orange")           $lb("Orange")
28              value   $lb("Orange","White")   $lb("Orange","White")   $lb("Orange","White")   $lb("Orange","White")
29              value   $lb("Black")    $lb("Black")    $lb("Black")    $lb("Black")
30              value   $lb("Red","Green")      $lb("Red","Green")      $lb("Red","Green")      $lb("Red","Green")
31              value   $lb("Purple")   $lb("Purple")   $lb("Purple")   $lb("Purple")
32              value   $lb("Green","Red")      $lb("Green","Red")      $lb("Green","Red")      $lb("Green","Red")
33      blank   blank   TX      blank           blank
34              value   $lb("Blue","Green")     $lb("Blue","Green")     $lb("Blue","Green")     $lb("Blue","Green")
35              value   $lb("Yellow")   $lb("Yellow")   $lb("Yellow")   $lb("Yellow")
36              value   $lb("Red","Blue")       $lb("Red","Blue")       $lb("Red","Blue")       $lb("Red","Blue")
37      blank   blank   HI      blank           blank
38      blank   blank   OR      blank           blank
39      blank   blank   NM      blank           blank
40      blank   blank   NJ      blank           blank
41      blank   blank   NY      blank           blank
42              value   $lb("Black","Orange")   $lb("Black","Orange")   $lb("Black","Orange")   $lb("Black","Orange")
43              value   $lb("Blue")     $lb("Blue")     $lb("Blue")     $lb("Blue")
44      blank   blank   MO      blank           blank
45              value   $lb("Purple","Yellow")  $lb("Purple","Yellow")  $lb("Purple","Yellow")  $lb("Purple","Yellow")
46              value   $lb("Orange")   $lb("Orange")           $lb("Orange")
47              value   $lb("Yellow","Green")   $lb("Yellow","Green")   $lb("Yellow","Green")   $lb("Yellow","Green")
48              value   $lb("Blue","Blue")      $lb("Blue","Blue")      $lb("Blue","Blue")      $lb("Blue","Blue")
49              value   $lb("Blue")     $lb("Blue")     $lb("Blue")     $lb("Blue")
50              value   $lb("White","Red")      $lb("White","Red")      $lb("White","Red")      $lb("White","Red")
51              value   $lb("White","Green")    $lb("White","Green")    $lb("White","Green")    $lb("White","Green")
52      blank   blank   MT      blank           blank
53              value   $lb("Red")      $lb("Red")      $lb("Red")      $lb("Red")
54      blank   blank   MD      blank           blank
55              value   $lb("Orange","Orange")  $lb("Orange","Orange")  $lb("Orange","Orange")  $lb("Orange","Orange")
56      blank   blank   MD      blank           blank
57              value   $lb("White")    $lb("White")    $lb("White")    $lb("White")
 
50 Rows(s) Affected
End of data
0
0 189
文章 姚 鑫 · 一月 19, 2022 3m read

第二十八章 SQL函数 CHAR_LENGTH

返回表达式中的字符数的函数。

大纲

CHAR_LENGTH(expression)

参数

  • expression - 表达式,可以是列名、字符串文字或另一个标量函数的结果。底层数据类型可以是字符类型(如CHARVARCHAR)、数字或数据流。

CHAR_LENGTH返回整数数据类型。

描述

CHAR_LENGTH返回一个整数值,表示指定表达式中的字符数,而不是字节数。表达式可以是字符串,也可以是任何其他数据类型,如数字或数据流字段。返回的整数计数包括前导和尾随空格以及字符串终止字符。如果传递NULL值,则CHARACTER_LENGTH返回NULL,如果传递空字符串(‘’)值,则返回0。

在计算字符之前,会将数字解析为规范形式;不会解析带引号的数字字符串。在下面的示例中,第一个CHAR_LENGTH返回1(因为数字分析删除了前导和尾随零),第二个CHAR_LENGTH返回8

SELECT CHAR_LENGTH(007.0000) AS NumLen,
       CHAR_LENGTH('007.0000') AS NumStringLen
       
1   8

注意:CHAR_LENGTHCHARACTER_LENGTHDATALENGTH函数是相同的。 它们都接受一个流字段参数。 LENGTH$LENGTH函数不接受流字段参数。

LENGTH与这些函数的不同之处在于,在计算字符之前会去掉尾随空格和字符串终止字符。

$LENGTH也不同于这些函数,因为如果传入一个NULL值,它返回0,如果传入一个空字符串,则返回0。 $LENGTH与其他长度函数的不同之处是返回数据类型SMALLINT; 所有其他长度函数返回的数据类型为INTEGER

示例

下面的示例返回Sample.Employee中状态缩写字段(Home_State)中的字符数。

(美国各州都有两个字母的邮政缩写):

SELECT DISTINCT CHAR_LENGTH(Home_State) AS StateLength
     FROM Sample.Employee

image

下面的例子返回员工的名字和每个员工名字中的字符数,按字符数升序排列:

SELECT Name,
     CHAR_LENGTH(Name) AS NameLength
     FROM Sample.Employee
     ORDER BY NameLength

image

以下示例返回Sample.Employee表中的字符流字段(Notes)和二进制流字段(Picture)中的字符数:

SELECT DISTINCT CHAR_LENGTH(Notes) AS NoteLen
     FROM Sample.Employee WHERE Notes IS NOT NULL
SELECT DISTINCT CHAR_LENGTH(Picture) AS PicLen
     FROM Sample.Employee WHERE Picture IS NOT NULL

下面的嵌入式SQL示例显示CHAR_LENGTH如何处理Unicode字符。CHAR_LENGTH计算字符数,而不考虑其字节长度:

    SET a=$CHAR(960)_"FACE"
    WRITE !,a
    &sql(SELECT CHAR_LENGTH(:a) INTO :b)
    IF SQLCODE'=0 {WRITE !,"Error code ",SQLCODE }
    ELSE {WRITE !,"The CHAR length is ",b }
    
    
5
0
0 120
文章 姚 鑫 · 一月 18, 2022 3m read

第二十七章 SQL函数 CHARINDEX

一个字符串函数,它返回子字符串在字符串中的位置,具有可选的搜索起点。

大纲

CHARINDEX(substring,string[,start])

参数

  • substring - 要在字符串中匹配的子字符串。
  • string - 作为子字符串搜索目标的字符串表达式。
  • start - 可选-子字符串搜索的起始点,指定为正整数。 从字符串开始的字符计数,从1开始计数。 若要从字符串的开头开始搜索,请忽略此参数或指定从01开始。 负数、空字符串、NULL或非数字值被视为0

CHARINDEX返回INTEGER数据类型。

描述

CHARINDEX在字符串中搜索子字符串。 如果找到匹配,则返回第一个匹配子字符串的起始位置,从1开始计算。 如果不能找到子字符串,CHARINDEX返回0

空字符串是一个字符串值。 因此,可以将空字符串用于任意一个字符串参数值。 start参数将空字符串值视为0。 但是,请注意ObjectScript空字符串作为NULL传递给 SQL。

NULL不是SQL中的字符串值。 因此,为任何一个CHARINDEX字符串参数指定NULL都会返回NULL

CHARINDEX不能将%Stream.GlobalCharacter字段用于字符串或子字符串参数。尝试这样做会生成SQLCODE-37错误。可以使用SUBSTRING函数获取%Stream.GlobalCharacter字段并返回%String数据类型值以供CHARINDEX使用。

CHARINDEX区分大小写。使用其中一个大小写转换函数查找字母或字符串的大写和小写实例。

此函数提供了与Transact-SQL实现的兼容性。

CHARINDEX, POSITION, $FIND和INSTR

CHARINDEX, POSITION$FINDINSTR都在字符串中搜索指定的子字符串,并返回与第一个匹配项对应的整数位置。 CHARINDEXPOSITIONINSTR返回匹配子字符串的第一个字符的整数位置。 $FIND返回匹配子字符串结束后第一个字符的整数位置。 CHARINDEX$FINDINSTR支持指定子字符串搜索的起始点。 INSTR还支持从起始点指定子字符串出现。

下面的示例演示了这四个函数,指定了所有可选参数。 注意,在这些函数中,stringsubstring的位置不同:

SELECT POSITION('br' IN 'The broken brown briefcase') AS Position,
       CHARINDEX('br','The broken brown briefcase',6) AS Charindex,
       $FIND('The broken brown briefcase','br',6) AS Find,
       INSTR('The broken brown briefcase','br',6,2) AS Inst

示例

下面的示例在一个核苷酸序列中搜索子字符串TTAGGG的首次出现。 它返回7,这个子字符串在字符串中的位置:

SELECT CHARINDEX('TTAGGG','TTAGTCTTAGGGACATTAGGG')

7

下面的示例搜索所有包含子字符串“Fred”Name字段值:

SELECT Name
FROM Sample.Person
WHERE CHARINDEX('Fred',Name)>0

以下示例使用SUBSTRING允许CHARINDEX搜索包含DNA核苷酸序列的%Stream.GlobalCharacter字段的前1000个字符,以查找子字符串TTAGGG的第一个匹配项:

SELECT CHARINDEX('TTAGGG',SUBSTRING(DNASeq,1,1000)) FROM Sample.DNASequences

以下示例匹配前10个字符后的子字符串:

SELECT CHARINDEX('Re','Reduce, Reuse, Recycle',10)

16

下面的示例指定超出字符串长度的起始位置:

SELECT CHARINDEX('Re','Reduce, Reuse, Recycle',99)

0

以下示例显示CHARINDEX处理空字符串(‘’)的方式与处理任何其他字符串值一样:

SELECT CHARINDEX('','Fred Astare'),
       CHARINDEX('A',''),
       CHARINDEX('','')

在上面的示例中,第一个和第二个CHARINDEX函数返回0(不匹配)。第三个函数返回1,因为空字符串与位置1处的空字符串匹配。

以下示例显示CHARINDEX不将NULL视为字符串值。为任一字符串指定NULL始终返回NULL

SELECT CHARINDEX(NULL,'Fred Astare'),
       CHARINDEX('A',NULL),
       CHARINDEX(NULL,NULL)
0
0 155
文章 姚 鑫 · 一月 16, 2022 1m read

第二十五章 SQL函数 CHAR

返回具有在字符串表达式中指定的ASCII代码值的字符的字符串函数。

大纲

CHAR(code-value)

{fn CHAR(code-value)}

参数

  • code-value - 与字符相对应的整数代码。

描述

Char返回与指定的整数代码值对应的字符。因为 IRIS是UNICODE系统,所以可以为任何UNICODE字符指定整数代码,从065535。如果code-value是超出允许值范围的整数,则CHAR返回NULL

如果代码值是非数字字符串,则CHAR返回一个空字符串('')。如果传递空值,CHAR返回NULL

请注意,CHAR可以用作ODBC标量函数(使用花括号语法),也可以用作SQL常规函数。

示例

以下示例均返回字符Z

SELECT CHAR(90) AS CharCode

Z
SELECT {fn CHAR(90)} AS CharCode

Z

下面的示例返回希腊字母lambda

ClassMethod Cast2()
{
	&sql(SELECT {fn CHAR(955)}
	   INTO :greeklet)
	w !,"Greek letter: ",greeklet
}

DHC-APP> d ##class(PHA.TEST.SQLCommand).Cast2()
 
Greek letter: λ
0
0 102
文章 姚 鑫 · 一月 14, 2022 2m read

第二十四章 SQL函数 CEILING

数值函数,返回大于或等于给定数值表达式的最小整数。

大纲

CEILING(numeric-expression)

{fn CEILING(numeric-expression)}

参数

  • numeric-expression - 要计算其上限的数字。

CELING返回与NUMERIC-EXPRESSION相同的数据类型。

描述

CELING返回大于或等于NUMERIC-EXPRESSION的最接近的整数值。返回值的小数位数为0。当numeric-expressionNULL值、空字符串(‘’)或任何非数字字符串时,CELING返回NULL

请注意,CELING可以作为ODBC标量函数(使用花括号语法)调用,也可以作为SQL常规函数调用。

也可以使用Ceuling()方法调用从ObjectScript调用此函数:

$SYSTEM.SQL.Functions.EILING(numeric-expression)

示例

以下示例显示了CEILING 如何将分数转换为其CEILING 整数:

SELECT CEILING(167.111) AS CeilingNum1,
       CEILING(167.456) AS CeilingNum2,
       CEILING(167.999) AS CeilingNum3
SELECT {fn CEILING(167.00)} AS CeilingNum1,
       {fn CEILING(167.00)} AS CeilingNum2
SELECT CEILING(-167.111) AS CeilingNum1,
       CEILING(-167.456) AS CeilingNum2,
       CEILING(-167.999) AS CeilingNum3
SELECT CEILING(-167.00) AS CeilingNum 

-167

下面的示例使用子查询将一个包含美国邮政编码(postal Codes)的简化为每个上限纬度整数的一个代表城市:

SELECT City,State,CEILING(Latitude) AS CeilingLatitude 
FROM (SELECT City,State,Latitude,CEILING(Latitude) AS CeilingNum
      FROM Sample.USZipCode)
GROUP BY CeilingNum
ORDER BY CeilingNum DESC
0
0 107
文章 姚 鑫 · 一月 13, 2022 3m read

第二十三章 SQL函数 CAST(二)

转换位值

可以将expr值转换为BIT以返回01。 如果expr1或任何其他非零数值,则返回1。 如果expr“TRUE”“TRUE”“TRUE”,则返回1。 (“True”可以用任何大小写组合表示,但不能缩写为“T”。) 如果expr是任何其他非数值值,则返回0。 如果expr0,则返回0

在下面的例子中,前5CAST操作返回1,后5CAST操作返回0:

SELECT CAST(1 AS BIT) AS One, 
       CAST(7 AS BIT) AS Num,      
       CAST(743.6 AS BIT) AS Frac,  
       CAST(0.3 AS BIT) AS Zerofrac,
       CAST('tRuE' AS BIT) AS TrueWord,
       CAST(0 AS BIT) AS Zero,  
       CAST('FALSE' AS BIT) AS FalseWord, 
       CAST('T' AS BIT) AS T,    
       CAST('F' AS BIT) AS F,   
       CAST(0.0 AS BIT) AS Zerodot     

示例

下面的示例使用CAST函数将平均值表示为整数,而不是浮点数。 请注意,CAST将数字截短,而不是四舍五入:

SELECT DISTINCT AVG(Age) AS AvgAge,
   CAST(AVG(Age) AS INTEGER) AS IntAvgAge
      FROM Sample.Person

下面的例子展示了CAST函数如何将pi(一个浮点数)转换为不同的数值数据类型:

SELECT 
   CAST({fn PI()} As INTEGER) As IntegerPi,
   CAST({fn PI()} As SMALLINT) As SmallIntPi,
   CAST({fn PI()} As DECIMAL) As DecimalPi,
   CAST({fn PI()} As NUMERIC) As NumericPi,
   CAST({fn PI()} As DOUBLE) As DoublePi

注意,在下面的例子中,精度和比例值被解析,但不会改变CAST返回的值:

SELECT 
   CAST({fn PI()} As DECIMAL) As DecimalPi,
   CAST({fn PI()} As DECIMAL(6,3)) As DecimalPSPi

下面的例子展示了CAST函数如何将pi(浮点数)转换为不同的字符数据类型:

SELECT 
   CAST({fn PI()} As CHAR) As CharPi,
   CAST({fn PI()} As CHAR(4)) As CharNPi,
   CAST({fn PI()} As CHAR VARYING) As CharVaryingPi,
   CAST({fn PI()} As VARCHAR(4)) As VarCharNPi

下面的例子展示了CAST函数如何将Name(一个字符串)转换为不同的字符数据类型:

SELECT DISTINCT 
   CAST(Name As CHAR) As CharName,
   CAST(Name As CHAR(4)) As CharNName,
   CAST(Name As CHAR VARYING) As CharVaryingName,
   CAST(Name As VARCHAR(4)) As VarCharNName
      FROM Sample.Person

下面的示例展示了使用CAST函数将Name(字符串)转换为不同的数字数据类型时会发生什么。 在任何情况下,返回值都是0 (0):

SELECT DISTINCT 
   CAST(Name As INT) As IntName,
   CAST(Name As SMALLINT) As SmallIntName,
   CAST(Name As DEC) As DecName,
   CAST(Name As NUMERIC) As NumericName
   FROM Sample.Person

下面的示例将日期字段(DOB)转换为数字数据类型和几个字符数据类型。 将日期转换为数字将返回等效的$HOROLOG整数。 将日期转换为字符数据类型将返回输入格式的日期字符串(CHAR VARYINGcharacter VARYING)或ODBC日期字符串格式的日期(部分或全部):

SELECT DISTINCT DOB,
   CAST(DOB As INT) AS IntDate,
   CAST(DOB As CHAR) AS CharDate,
   CAST(DOB As CHAR(6)) AS CharNDate,
   CAST(DOB As CHAR VARYING) AS CharVaryDate,
   CAST(DOB As VARCHAR(10)) AS VarCharNDate
      FROM Sample.Person

下面的示例将字符串转换为DATETIME数据类型:

SELECT CAST('1936-11-26' As DATE) AS StringToDate,
       CAST('14:33:45.78' AS TIME) AS StringToTime

日期只能转换为YYYY-MM-DD格式的字符串。 其他格式的字符串返回0。 请注意,在将字符串转换为TIME数据类型时,小数秒被截断(而不是四舍五入)。

下面的例子将日期转换为TIMESTAMP数据类型:

SELECT DISTINCT DOB,
   CAST(DOB As TIMESTAMP) AS DateToTstamp
      FROM Sample.Person

生成的时间戳格式为“YYYY-MM-DD hh:mm:ss”

下面的示例将字符串转换为TIME数据类型,然后将结果时间转换为TIMESTAMP数据类型:

SELECT CAST(CAST('14:33:45.78' AS TIME) As TIMESTAMP) AS TimeToTstamp

生成的时间戳格式为“YYYY-MM-DD hh:mm:ss”。 时间部分由嵌套的CAST提供; 日期部分是当前系统日期。

0
0 92
文章 姚 鑫 · 一月 12, 2022 9m read

第二十二章 SQL函数 CAST(一)

将给定表达式转换为指定数据类型的函数。

大纲

CAST(expr AS CHAR | CHARACTER | VARCHAR | NCHAR | NVARCHAR)
CAST(expr AS CHAR(n) | CHARACTER(n) | VARCHAR(n) )
CAST(expr AS CHAR VARYING | CHARACTER VARYING)
CAST(expr AS INT | INTEGER | BIGINT | SMALLINT | TINYINT)
CAST(expr AS DEC | DECIMAL | NUMERIC)
CAST(expr AS DEC(p[,s]) | DECIMAL(p[,s]) | NUMERIC(p[,s]) )
CAST(expr AS DOUBLE)
CAST(expr AS MONEY | SMALLMONEY)
CAST(expr AS DATE)
CAST(expr AS TIME)
CAST(expr AS POSIXTIME)
CAST(expr AS TIMESTAMP | DATETIME | SMALLDATETIME)
CAST(expr AS BIT)
CAST(expr AS BINARY | BINARY VARYING | VARBINARY)
CAST(expr AS BINARY(n) | BINARY VARYING(n) | VARBINARY(n) )
CAST(expr AS GUID)

参数

  • expr - SQL表达式,通常是表的文字或数据字段。
  • n - 一个整数,指示要返回的最大字符数。 如果n小于expr数据,返回的数据将被截断为n个字符。 如果n大于expr数据,则不执行填充。
  • p,s - 可选 - p=精度(最大总位数),整数形式。 s=刻度(十进制数字的最大值),用整数表示。 如果未指定比例,则默认为15

描述

SQL CAST函数将表达式的数据类型转换为指定的数据类型。当Expr的数据类型是标准数据类型或标准数据类型(如%Library.String%Library.Time%Library.Date%Library.TimeStamp)的子类时,CAST可以转换该数据类型。

可以将expr转换为以下任何数据类型

  • CHARCHARACTER:用其初始字符表示数字或字符串。 当指定为CASTCONVERT时,不带nVARCHAR默认长度为30个字符。 否则,VARCHAR数据类型(没有指定大小)将被映射到一个1个字符的MAXLEN,如data Types表所示。 NCHAR等价于CHAR; NVARCHAR相当于VARCHAR
  • CHAR(n)CHARACTER(n)VARCHAR(n):用n指定的字符数表示数字或字符串。
  • CHAR VARYINGCHARACTER VARYING:用原值中的字符数表示数字或字符串。
  • INTINTEGERBIGINTSMALLINTTINYINT:用整数部分表示数字。 十进制数字被截断。
  • “DEC”“DECIMAL”“NUMERIC”:用原值中的位数来表示数字。 使用 $DECIMAL函数进行转换,该函数将$DOUBLE值转换为$DECIMAL值。 如果指定了p(精度),则保留为定义的数据类型的一部分,但不会影响CAST返回的值。 如果指定正整数的s (scale)值,则十进制值四舍五入为指定的位数。 (在Display模式中包含适当数量的尾随零,但在Logical模式和ODBC模式中被截断。) 如果指定s=0,数值将四舍五入为整数。 如果指定s=-1,数值将被截断为整数。
  • DOUBLE表示IEEE浮点标准。
  • MONEYSMALLMONEY是货币数字数据类型。 货币数据类型的规模总是4
  • DATE:日期。 日期可以用以下任何一种格式表示,这取决于上下文:所在地区的显示日期格式(例如,MM/DD/YYYY); ODBC日期格式(YYYY-MM-DD); 或$HOROLOG整数日期存储格式(nnnnn)。 必须将$HOROLOG日期部分值指定为整数,而不是数字字符串。
  • TIME:时间。 时间可以用以下任何一种格式表示,这取决于上下文:本地地区的显示时间格式(例如,hh:mm:ss); ODBC日期格式(hh:mm:ss); 或$HOROLOG整数时间存储格式(nnnnn)。 必须将$HOROLOG时间部分值指定为整数,而不是数字字符串。
  • POSIXTIME:以64位有符号整数的形式表示日期和时间戳。
  • TIMESTAMPDATETIMESMALLDATETIME:日期和时间戳,格式为YYYY-MM-DD hh:mm:ss.nnn。 这对应于ObjectScript $ZTIMESTAMP特殊变量。
  • BIT表示单个二进制值。
  • BINARYBINARY VARINGVARBINARY表示数据类型%Library.Binary(xDBC数据类型BINARY)的值。对于BINARY,可选的n长度缺省为1,对于BINARY VARINGVARBINARY,缺省为30。转换为二进制值时,实际上不会执行数据转换。不会截断指定长度为n的值的长度。
  • GUID表示数据类型%Library.UniqueIdentifier36个字符值。如果提供的expr超过36个字符,CAST将返回expr的前36个字符。要生成GUID值,请使用%SYSTEM.Util.CreateGUID()方法。

转换数字

数值可以转换为数字数据类型或字符数据类型。

当将数值结果转换为缩略值时,数值将被截断,而不是四舍五入。例如,将98.765转换为INT返回98,转换为CHAR返回9,转换为CHAR(4)返回98.7。请注意,将负数转换为CHAR仅返回负号,将小数转换为CHAR仅返回小数点。

数字可以由数字09、小数点、一个或多个前导符号(+-)、指数符号(EE)后面最多跟一个+-符号组成。 数字不能包含组分隔符(逗号)。

在执行强制转换之前 SQL将数字解析为其规范形式:执行指数运算。 IRIS带前导和后导零、前导加号和后导小数点。 在转换数字之前解析多个符号。 然而,SQL将双负号作为注释指示符; 遇到数字中的双负号时,会将该行代码的其余部分作为注释处理。

浮点数可以采用DECDECIMALNUMERIC数据类型。 DOUBLE数据类型根据IEEE浮点标准表示浮点数。 浮点数据类型比DOUBLE数据类型具有更高的精度,适合于大多数应用程序。 不能使用CAST将浮点数转换为DOUBLE数据类型; 相反,使用ObjectScript $DOUBLE函数。

当数字值被转换为日期或时间数据类型时,它在SQL中显示为0 (0); 但是,当将数字转换为日期或时间时,从嵌入式SQL传递到ObjectScript,它显示为相应的$HOROLOG值。

字符串类型转换

可以将字符串强制转换为另一种字符数据类型,返回单个字符、前n个字符或整个字符串。

在执行强制转换之前,SQL会解析内嵌的引号字符('can' t'=can't)和字符串连接('can'||'not'=cannot)。 保留前导和尾随空格。

当字符串被转换为数字类型时,它总是返回一个数字零(0)。

转换为DATE、TIME和TIMESTAMP

可以将字符串强制转换为DATETIMETIMESTAMP数据类型。 通过以下操作,可以得到一个有效的值:

  • DATE:格式为“yyyy-mm-dd”的字符串可以转换为DATE。 此字符串格式对应于ODBC日期格式。 执行值和范围检查。 年份必须在00019999之间(包括),从01月到12月,以及该月的适当日期(例如,02/29只在闰年有效)。 无效日期,如2013-02-29返回1840-12-31(逻辑日期0)。

将添加月和日字段中缺少的前导零。此转换的显示方式取决于显示模式和区域设置的日期显示格式。例如,‘2004-11-23’可能显示为‘11/23/2004’。在嵌入式SQL中,此强制转换作为相应的$HOROLOG日期整数返回。无效的ODBC日期或非数字字符串在转换为日期时在逻辑模式下表示为0;日期0显示为1840-12-31

  • TIME:格式为'hh:mm''hh:mm:ss''hh:mm:ss'的字符串。 nn'(有任意n个小数秒位数)可以被转换为TIME。 此字符串格式对应于ODBC时间格式。 执行值和范围检查。 缺少前导零被添加。 在嵌入式SQL中,这种转换将作为相应的$HOROLOG时间整数返回。 当转换为time时,无效的ODBC时间或非数字字符串在逻辑模式中表示为0; 时间0显示为00:00:00

  • TIMESTAMP:由有效日期和时间、有效日期或有效时间组成的字符串可以转换为TIMESTAMP。 日期部分可以采用多种格式。 缺少的日期部分默认为1841-01-01。 缺少的时间段默认为00:00:00。 缺少前导零将添加到月和日。 小数秒(如果指定了)可以在句点(.)或冒号(:)之前加上。 这些符号有不同的含义。 句号表示标准分数; 因此,12:00:00.4表示十分之四秒,而12:00:00.004表示千分之四秒。 冒号表示接下来的是千分之一秒; 因此12:00:00:4表示千分之四秒。 冒号后面的数字限制为3位。

转换NULL和空字符串

NULL可以转换为任何数据类型并返回NULL

空字符串(")的类型转换如下:

  • 所有字符数据类型返回NULL
  • 所有数字数据类型都返回0(零),以及尾随分数零的适当数量。 DOUBLE数据类型返回零,不带尾随分数零。
  • DATE数据类型返回12/31/1840
  • TIME数据类型返回00:00:00
  • TIMESTAMPDATETIMESMALLDATETIME数据类型返回NULL
  • BIT数据类型返回0
  • 所有二进制数据类型都返回NULL

转换日期

可以将日期转换为日期数据类型、数字数据类型或字符数据类型。

将日期转换为POSIXTIME数据类型会将时间戳转换为编码的64位带符号整数。 由于日期没有时间部分,时间部分被提供给时间戳编码为00:00:00CAST执行日期验证; 如果expr值不是有效日期,则会发出SQLCODE -400错误。

将日期转换为TIMESTAMPDATETIMESMALLDATETIME数据类型将返回一个格式为YYYY-MM-DD hh:mm:ss的时间戳。 由于日期没有时间部分,因此生成的时间戳的时间部分总是00:00:00CAST执行日期验证; 如果expr值不是有效日期,则会发出SQLCODE -400错误。

下面的动态SQL示例将DATE数据类型字段转换为TIMESTAMPPOSIXTIME:

ClassMethod Cast()
{
	s myquery = 2
	s myquery(1) = "SELECT TOP 5 DOB,CAST(DOB AS TIMESTAMP) AS TStamp,"
	s myquery(2) = "CAST(DOB AS POSIXTIME) AS Posix FROM Sample.Person"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(.myquery)
	if qStatus '= 1 {
		w "%Prepare failed:" 
		d $System.Status.DisplayError(qStatus) 
		q
	}
	s rset = tStatement.%Execute()
	d rset.%Display()
	w !,"End of data"
}
d ##class(PHA.Test).Cast()
DOB	TStamp	Posix
1976-03-01	1976-03-01 00:00:00	1976-03-01 00:00:00
2008-07-25	2008-07-25 00:00:00	2008-07-25 00:00:00
1976-03-30	1976-03-30 00:00:00	1976-03-30 00:00:00
1961-07-29	1961-07-29 00:00:00	1961-07-29 00:00:00
1924-03-10	1924-03-10 00:00:00	1924-03-10 00:00:00

5 Rows(s) Affected
End of data

注:IRIS以下不可用POSIXTIME

下面的动态SQL示例将TIMESTAMP数据类型字段转换为DATEPOSIXTIME:

ClassMethod Cast1()
{
	s myquery = 2
	s myquery(1) = "SELECT TOP 5 EventDate,CAST(EventDate AS DATE) AS Horolog,"
	s myquery(2) = "CAST(EventDate AS POSIXTIME) AS Posix FROM Aviation.Event"
	s tStatement = ##class(%SQL.Statement).%New()
	s qStatus = tStatement.%Prepare(.myquery)
	if qStatus '= 1 {
		w "%Prepare failed:" 
		d $System.Status.DisplayError(qStatus) 
		q
	}
	s rset = tStatement.%Execute()
	d rset.%Display()
	w !,"End of data"
}

将日期转换为数字数据类型将返回该日期的$HOROLOG值。 这是一个整数值,表示自1840年12月31日以来的天数。

将日期转换为字符数据类型可以返回完整的日期,也可以返回数据类型长度所允许的全部日期。 但是,对所有字符数据类型来说,显示格式并不相同。 CHAR VARYINGCHARACTER VARYING数据类型以显示格式返回完整的日期。 例如,如果日期显示为MM/DD/YYYY,这些数据类型将日期返回为具有相同格式的字符串。 其他字符数据类型以ODBC日期格式的字符串形式返回日期(或其中的一部分)。 例如,如果日期显示为mm/dd/yyyy,这些数据类型将日期返回为yyyy - mm - dd格式的字符串。 因此,对于日期04/24/2004,CHAR数据类型返回'2'(年份的第一个字符),而CHAR(8)返回' 2004-04 - '

0
0 339
文章 姚 鑫 · 一月 11, 2022 1m read

第二十一章 SQL函数 ATAN2

接受两个坐标并返回以弧度为单位的反正切角的标量数值函数。

注意:IRIS可用,IRIS以下不可用。

大纲

{fn ATAN2(y,x)}

参数

  • y - 指定y轴坐标的数值表达式。
  • x - 指定x轴坐标的数值表达式。

ATAN2返回NUMERICDOUBLE数据类型。 如果数值表达式是数据类型DOUBLE, ATAN2返回DOUBLE; 否则,返回NUMERIC

描述

ATAN2采用射线(y,x)的笛卡尔坐标,并以浮点数的形式返回角的正切反(弧)。 用两个坐标的符号来确定笛卡尔坐标。 当x为正值时,ATAN2返回与ATAN(y/x)相同的值。 如果传递一个NULL值,ATAN2将返回NULLATAN2将非数字字符串(包括空字符串("))视为数字值0

ATAN2返回一个精度为36、刻度为18的值。

ATAN2只能用作ODBC标量函数(使用花括号语法)。

可以使用DEGREES函数将弧度转换为角度。 可以使用RADIANS函数来转换角度到弧度。

示例

下面的例子调用ATAN2:

SELECT {fn ATAN2(15,30)} AS ArcTangent 

0.463647609000806116
0
0 89
文章 姚 鑫 · 一月 10, 2022 1m read

第二十章 SQL函数 ATAN

一个标量数值函数,返回角的正切的弧切值(以弧度为单位)。

大纲

{fn ATAN(numeric-expression)}

参数

  • numeric-expression - 一个数值表达式。 这是这个角的正切。

ATAN返回NUMERICDOUBLE数据类型。 如果数值表达式是数据类型DOUBLE, ATAN返回DOUBLE; 否则,返回NUMERIC

描述

ATAN接受任何数值,并以浮点数返回角度正切的反(弧)值。 如果传递一个NULL值,ATAN将返回NULLATAN将非数字字符串(包括空字符串("))视为数字值0

ATAN返回一个精度为36、刻度为18的值。

ATAN只能用作ODBC标量函数(使用花括号语法)。

可以使用DEGREES函数将弧度转换为角度。 可以使用RADIANS函数来转换角度到弧度。

示例

下面的例子展示了ATAN的效果:

SELECT {fn ATAN(0.52)} AS ArcTangent 

0.479519291992596165
0
0 99
文章 姚 鑫 · 一月 9, 2022 1m read

第十九章 SQL函数 ASIN

一个标量数值函数,返回角的正弦的反正弦(以弧度为单位)。

大纲

{fn ASIN(numeric-expression)}

参数

  • numeric-expression - 数值在-1到1之间的数值表达式。 这是这个角的正弦值。

ASIN返回NUMERICDOUBLE数据类型。 如果数值表达式是数据类型DOUBLE, ASIN返回DOUBLE; 否则,返回NUMERIC

描述

ASIN以浮点数的形式返回角度正弦的反(弧)值。 numeric-expression的值必须是有符号的十进制数,取值范围为1 ~ -1(含1)。 超出此范围的数字将导致运行时错误,生成SQLCODE -400(发生致命错误)。 如果传递一个NULL值,ASIN将返回NULLASIN将非数字字符串(包括空字符串("))视为数字值0

ASIN返回一个精度为19、刻度为18的值。

ASIN只能用作ODBC标量函数(使用花括号语法)。

可以使用DEGREES函数将弧度转换为角度。 可以使用RADIANS函数来转换角度到弧度。

示例

下面的例子展示了ASIN对两个正弦的影响。

SELECT {fn ASIN(0.52)} AS ArcSine 

0.54685095069594411
SELECT {fn ASIN(-1.00)} AS ArcSine 

-1.570796326794896619
0
0 137
文章 姚 鑫 · 一月 8, 2022 1m read

第十八章 SQL函数 ASCII

一个字符串函数,返回字符串表达式的第一个(最左边)字符的整型ASCII码值。

大纲

ASCII(string-expression)

{fn ASCII(string-expression)}

参数

  • string-expression - 字符串表达式,它可以是列的名称、字符串字面值或另一个标量函数的结果,其中基础数据类型可以表示为任何字符类型(如CHARVARCHAR)。 CHARVARCHAR类型的字符串表达式。

描述

如果传入一个NULL或空字符串值,ASCII将返回NULL。 空字符串返回NULLSQL Server一致。

SELECT ASCII('Z') AS AsciiCode

90
SELECT {fn ASCII('ZEBRA')} AS AsciiCode 

90

在执行ASCII转换之前,SQL将数字转换为规范形式。 下面的例子返回55,它是数字7的ASCII值:

SELECT ASCII(+007) AS AsciiCode

55

如果数字以字符串的形式表示,则不执行此数字解析。 下面的例子返回43,它是加(+)字符的ASCII值:

SELECT ASCII('+007') AS AsciiCode 

43
0
0 129
文章 姚 鑫 · 一月 7, 2022 1m read

第十七章 SQL函数 ACOS

一个标量数值函数,返回给定余弦的弧余弦(以弧度为单位)。

大纲

{fn ACOS(numeric-expression)}

参数

  • numeric-expression - 数值在-1到1之间的数值表达式。 这是这个角的余弦值。

ACOS返回NUMERICDOUBLE数据类型。 如果数值表达式是数据类型DOUBLE, ACOS返回DOUBLE; 否则,返回NUMERIC

描述

ACOS接受一个数值并以浮点数的形式返回余弦的反(弧)值。 numeric-expression的值必须是有符号的十进制数,取值范围为1 ~ -1(含1)。 超出此范围的数字将导致运行时错误,生成SQLCODE -400(发生致命错误)。 如果传入NULL值,ACOS将返回NULLACOS将非数字字符串(包括空字符串("))视为数字值0。

ACOS返回一个精度为19、刻度为18的值。

ACOS只能用作ODBC标量函数(使用花括号语法)。

可以使用DEGREES函数将弧度转换为角度。 可以使用RADIANS函数来转换角度到弧度。

示例

下面的例子展示了ACOS对两个余弦的影响:

SELECT {fn ACOS(0.52)} AS ArcCosine 

1.02394537609895251
SELECT {fn ACOS(-1)} AS ArcCosine

3.141592653589793238
0
0 85
文章 姚 鑫 · 一月 6, 2022 1m read

第十六章 SQL函数 ABS

返回数值表达式的绝对值的数值函数。

大纲

ABS(numeric-expression)

{fn ABS(numeric-expression)}

参数

  • numeric-expression - 要返回其绝对值的数字。

ABS返回与数字表达式相同的数据类型。

描述

ABS返回绝对值,它总是0或正数。 如果数值表达式不是一个数字(例如,字符串'abc',或空字符串''),ABS返回0。 当传递null值时,ABS返回<null>

请注意,ABS可以用作ODBC标量函数(带有花括号语法),也可以用作SQL通用函数。

这个函数也可以通过调用ABS()方法从ObjectScript中调用:

  WRITE $SYSTEM.SQL.Functions.ABS(-0099)

示例

下面的例子展示了ABS的两种形式:

SELECT ABS(-99) AS AbsGen,{fn ABS(-99)} AS AbsODBC

下面的例子展示了ABS如何处理其他一些数字。 在调用ABS之前, SQL将数字表达式转换为规范形式,删除前导和末尾的零,并计算指数。

SELECT ABS(007) AS AbsoluteValue

7
SELECT ABS(-0.000) AS AbsoluteValue

0
SELECT ABS(-99E4) AS AbsoluteValue

990000
SELECT ABS(-99E-4) AS AbsoluteValue

.0099
0
0 76
文章 姚 鑫 · 一月 5, 2022 3m read

第十五章 SQL窗口函数概述(二)

ROW子句

ROW子句可以与FIRST_VALUE(字段)和SUM(字段)窗口函数一起使用。 可以为其他windows函数指定它,但不执行任何操作(有或没有ROWS子句的结果相同)。

ROWS子句有两种语法形式:

ROWS framestart
ROWS BETWEEN framestart AND frameend

Framestartframeend有五个可能的值:

UNBOUNDED PRECEDING                    /* 从当前分区的开头开始 */
offset PRECEDING   /* 开始偏移当前行之前的行数 */
CURRENT ROW                                      /* 从当前行开始 */
offset FOLLOWING  /* 继续偏移当前行后面的行数 */
UNBOUNDED FOLLOWING                  /* 继续到当前分区的末尾 */

ROWS子句语法可以在两个方向上指定一个范围。 例如,在无界前面和1后面之间的行以及在1后面和无界前面之间的行是完全相等的。

ROWS框架的开始语法默认为CURRENT ROW作为范围的第二个未指定的边界。 因此,以下是等价的:

  
ROWS UNBOUNDED PRECEDINGROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
ROWS 1 PRECEDINGROWS BETWEEN 1 PRECEDING AND CURRENT ROW
ROWS CURRENT ROWROWS BETWEEN CURRENT ROW AND CURRENT ROW
ROWS 1 FOLLOWINGROWS BETWEEN CURRENT ROW AND 1 FOLLOWING
ROWS UNBOUNDED FOLLOWINGROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

如果没有指定ROWS子句,则默认为在无界的前一行和当前行之间的行数。

ROW子句示例

下面的查询返回包含大量“噪声noise”(随机变量)的分数。ROWS子句用于“平滑smooth”这些变化,方法是按排序顺序将每个分数与其前一个分数和紧随其后的分数相加,然后除以3,得到滚动平均分数:

SELECT Item,Score,SUM(Score)
  OVER (ORDER BY Score ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)/3
  AS CohortScore FROM Sample.TestScores

操作为:(PrecedingScore+CurrentScore+FollowingScore)/3,注意底部和顶部的CohortScore值不准确,因为它们是将0加到两个计分值上,然后除以3(0+CurrentScore+FollowingScore)/3(PrecedingScore+CurrentScore+0)/3

使用窗口函数

窗口函数可用于:

  • SELECT list as a listed select-item.

窗口函数不能嵌入到子查询或选择项列表中的聚合函数中。

  • ORDER BY clause.

窗口函数不能在and ONWHERE、GROUP BYHAVING子句中使用。 尝试这样做会导致SQLCODE -367错误。

列名和别名

默认情况下,分配给窗口函数结果的列名是Window_n,其中n号后缀是列序号,正如在SELECT列表中指定的那样。 因此,下面的例子创建了列名Window_3Window_6:

SELECT Name,Home_State,ROW_NUMBER() OVER (PARTITION BY Home_State),Age,AVG(Age),ROW_NUMBER() OVER (ORDER BY Age)
FROM Sample.Person

如果要指定另一个列名(列别名),请使用AS关键字:

SELECT Name,State,ROW_NUMBER() OVER (PARTITION BY State) AS StateRow,Age
FROM Sample.Person

可以使用列别名在ORDER BY子句中指定一个窗口字段:

SELECT Name,State,ROW_NUMBER() OVER (PARTITION BY State) AS StateRow,Age
FROM Sample.Person
ORDER BY StateRow

不能在ORDER BY子句中使用默认的列名(如Window_3)。

ORDER BY

因为在窗口函数求值之后,ORDER BY子句应用于查询结果集,所以ORDER BY不会影响选择项窗口函数分配的值。

0
0 121
文章 姚 鑫 · 一月 4, 2022 6m read

第十四章 SQL窗口函数概述(一)

指定用于计算聚合和排名的每行“窗口框架”的函数。

窗口函数和聚合函数

在应用WHEREGROUP byHAVING子句之后,窗口函数对SELECT查询选择的行进行操作。

窗口函数将一组行中的一个(或多个)字段的值组合在一起,并在结果集中为生成的列中的每一行返回一个值。

虽然窗口函数与聚合函数类似,因为它们将多行结果组合在一起,但它们与聚合函数的不同之处在于,它们本身并不组合行。

窗函数的语法

窗口函数被指定为SELECT查询中的选择项。 窗口函数也可以在SELECT查询的ORDER BY子句中指定。

窗口函数执行与由PARTITION by子句、ORDER by子句和ROWS子句指定的逐行窗口相关的任务,并为每一行返回一个值。 这三个子句都是可选的,但是如果指定了,必须按照以下语法中的顺序指定:

window-function() OVER (
                      [ PARTITION BY partfield ]
                      [ ORDER BY orderfield ]
                      [ ROWS framestart ] | [ ROWS BETWEEN framestart AND frameend ]
                      )

其中framestartframeend可以是:

UNBOUNDED PRECEDING |
offset PRECEDING |
CURRENT ROW |
UNBOUNDED FOLLOWING |
offset FOLLOWING
  • window-function:支持如下窗口函数:ROW_NUMBER()RANK()PERCENT_RANK()FIRST_VALUE(字段)SUM(字段)。 该字段在显示的地方是必需的,在没有显示的地方是不允许的。 括号对所有窗口函数都是必需的。
  • OVER: OVER关键字后面必须加上括号。 括号中的子句是可选的。
  • PARTITION BY partfield:一个可选子句,根据指定的partfield分区行。 Partfield可以是单个字段,也可以是用逗号分隔的字段列表。 partfield可以是聚合函数、标量函数(如LENGTH(Name)ROUND(Salary,-2)),或者表达式(如Salary+Bonus)。 部分字段不能是流字段; 尝试这样做会产生一个SQLCODE -37错误。 如果指定了PARTITION BY,必须在ORDER BY之前指定PARTITION BY

如果指定了一个PARTITION BY子句,行被分组在指定的窗口中,窗口函数创建一个新的结果集字段并为每一行分配一个值。 例如,PARTITION BY City将共享相同City字段值的所有行分组到同一个窗口中; 窗口函数根据这个分组分配行值。

  • ORDER BY orderfield:一个可选子句,根据指定的orderfield对行排序。 Orderfield可以是单个字段,也可以是用逗号分隔的字段列表。 订单字段可以是一个聚合函数,一个标量函数(例如LENGTH(Name)ROUND(Salary,-2)),或者一个表达式(例如Salary+Bonus)。 订单字段不能是流字段; 尝试这样做会产生一个SQLCODE -37错误。

ORDER BY按排序规则升序对窗口函数值进行排序。如果指定PARTITION BYORDER BY,则行将被分区为组,每个组的orderfield值将被排序,窗口函数将创建一个新的结果集字段并为每行赋值。如果在没有PARTITION BY子句的情况下指定ORDER BY子句,则所有选定的行将在单个窗口中分组、排序,然后赋值。例如,ORDER BY City根据City字段的值对所有行进行排序,然后Window函数按该顺序为每行赋值。

  • ROWS:具有两种支持的语法形式的可选子句:ROWSFRAME STARTROWS介于Frame StartFrameEnd之间。ROWS通过指定分区内的起始点和结束点(包括范围点),对分区内的连续行执行滚动操作。它需要一个ORDER BY子句来建立行序列。它可以选择性地指定PARTITION BY子句。如果未指定ROWS子句,则缺省值为从分区开始处(前面未绑定)到当前行。ROWS子句可以与first_value(Field)sum(Field)窗口函数一起使用。

简单的例子

CityTable包含具有以下值的行:

NameCity
AbleNew York
BettyBoston
CharlieParis
DavisBoston
EveParis
FrancisParis
GeorgeLondon
BeatrixParis

ROW_NUMBER()窗口函数根据指定的窗口为每一行分配一个唯一的连续整数。

SELECT Name,City,ROW_NUMBER() OVER (PARTITION BY City) FROM CityTable
NameCityWindow_3
AbleNew York1
BettyBoston1
CharlieParis1
DavisBoston2
EveParis2
FrancisParis3
GeorgeLondon1
BeatrixParis4
SELECT Name,City,ROW_NUMBER() OVER (ORDER BY City) FROM CityTable

本例将所有行视为单个分区。 它根据City值对行排序,并返回以下结果:

NameCityWindow_3
AbleNew York4
BettyBoston1
CharlieParis5
DavisBoston2
EveParis6
FrancisParis7
GeorgeLondon3
BeatrixParis8
SELECT Name,City,ROW_NUMBER() OVER (Partition BY City ORDER BY Name) FROM CityTable

这个例子根据City值对行进行分区,根据Name值对每个City分区排序,并返回以下结果:

NameCityWindow_3
AbleNew York1
BettyBoston1
CharlieParis2
DavisBoston2
EveParis3
FrancisParis4
GeorgeLondon1
BeatrixParis1

NULL

PARTITION BY子句将字段为NULL(没有分配值)的行作为分区组处理。 例如,ROW_NUMBER() OVER (Partition BY City)会将没有City值的行分配为顺序整数,就像它将顺序整数分配给City值为'Paris'的行一样。

ORDER BY子句将字段为NULL(没有分配值)的行按照在任何分配值(具有最低的排序值)之前的顺序处理。 例如,ROW_NUMBER() OVER (ORDER BY City)首先将顺序整数分配给没有City值的行,然后将顺序整数分配给排序顺序中具有City值的行。

ROWS子句将NULL(没有赋值)的字段视为值为零。 例如,SUM(Scores) OVER (ORDER BY Scores ROWS 1 above)/2将分配0.00给所有没有分数值的行((0 + 0)/2),并通过将0加到它然后除以2来处理第一个分数值。

支持的窗口函数

支持以下窗口函数:

  • FIRST_VALUE(field)——将指定窗口中第一行(ROW_NUMBER()=1)的字段列的值赋给该窗口中的所有行。 例如:FIRST_VALUE(Country) OVER (PARTITION BY City)FIRST_VALUE()支持ROWS子句。 注意,NULL排序在所有值之前,所以如果第一行中的字段值是NULL,那么窗口中的所有行都将是NULL
  • PERCENT_RANK()——将排名百分比作为0到1(包括1)之间的小数分配给同一窗口中的每一行。 如果窗口函数字段的多个行包含相同的值,那么排名百分比可能包含重复的值。
  • RANK()——给同一窗口中的每一行分配一个排序整数,从1开始。 如果窗口函数字段的多个行包含相同的值,那么对整数的排序可以包含重复的值。
  • ROW_NUMBER()——为同一窗口中的每一行分配一个唯一的连续整数,从1开始。 如果多行窗口函数字段包含相同的值,则为每一行分配一个唯一的连续整数。
  • SUM(field)——将指定窗口中字段列值的和赋给该窗口中的所有行。

SUM既可以用作聚合函数,也可以用作窗口函数。 SUM()支持ROWS子句。

下面的例子比较了这些窗口函数中ORDER by子句返回的值:

SELECT Name,City,ROW_NUMBER() OVER (ORDER BY City) AS RowNum,
  RANK() OVER (ORDER BY City) AS RankNum,
  PERCENT_RANK() OVER (ORDER BY City) AS RankPct
  FROM CityTable ORDER BY City

本例将所有行视为单个分区。 它根据City值对行排序,并返回以下结果:

NameCityRowNumRankNumRankPct
Harriet 110
BettyBoston22.1111111111111111111
DavisBoston32.1111111111111111111
GeorgeLondon44.3333333333333333333
AbleNew York55.4444444444444444444
CharlieParis66.5555555555555555555
EveParis76.5555555555555555555
FrancisParis86.5555555555555555555
BeatrixParis96.5555555555555555555
JacksonRome10101
0
0 1391
文章 姚 鑫 · 一月 3, 2022 4m read

第十三章 SQL聚合函数 XMLAGG

一个聚合函数,它创建一个串接的值字符串。

大纲

XMLAGG([ALL | DISTINCT [BY(col-list)]] string-expr [%FOREACH(col-list)] [%AFTERHAVING])

参数

  • ALL - 可选-指定XMLAGG返回string-expr的所有值的连接字符串。 如果没有指定关键字,这是默认值。
  • DISTINCT - 可选-一个DISTINCT子句,指定XMLAGG返回一个只包含唯一string-expr值的连接字符串。 DISTINCT可以指定BY(colo -list)子句,其中colo -list可以是单个字段,也可以是用逗号分隔的字段列表。
  • string-expr - 计算结果为字符串的SQL表达式。 通常,这是要从其中检索数据的列的名称。
  • %FOREACH(col-list) - 可选-列名或以逗号分隔的列名列表。
  • %AFTERHAVING - 可选-应用在HAVING子句中的条件。

描述

XMLAGG聚合函数返回由string-expr中的所有值组成的串接字符串。 返回值的数据类型为VARCHAR,默认长度为4096

  • 一个简单的XMLAGG(或XMLAGG ALL)返回一个字符串,该字符串包含一个由所选行中string-expr的所有值组成的连接字符串。 string-exprNULL的行将被忽略。

以下两个示例都返回相同的单个值,即Sample.Person表的Home_State列中列出的所有值的串联字符串。

SELECT XMLAGG(Home_State) AS All_State_Values
FROM Sample.Person
SELECT XMLAGG(ALL Home_State) AS ALL_State_Values
FROM Sample.Person

请注意,此连接字符串包含重复值。

  • XMLAGG DISTINCT返回由所选行中string-expr的所有不同(唯一)值组成的连接字符串:XMLAGG(DISTINCT COL1)。将忽略string-exprNULL的行。XMLAGG(DISTINCT BY(Col2)col1)返回一个串联字符串,该字符串仅包含col2值不同(唯一)的记录中的col1字段值。然而,请注意,不同的col2值可以包括单个NULL作为不同的值。

返回值中将省略string-expr为NULL的行。如果至少返回一个非空字符串值,则从返回值中省略string-expr为空字符串('')的行。如果唯一非空的string-expr值是空字符串(''),则返回值是单个空字符串。

XMLAGG不支持数据流字段。为string-expr指定流字段会导致SQLCODE-37

XML和XMLAGG

XMLAGG的一个常见用法是标记列中的每个数据项。这是通过组合XMLAGGXMLELEMENT来实现的,如下例所示:

SELECT XMLAGG(XMLELEMENT("para",Home_State))
FROM Sample.Person

这将产生如下所示的输出字符串:

<para>LA</para><para>MN</para><para>LA</para><para>NH</para><para>ME</para>...

XMLAGG和ORDER BY

XMLAGG函数将来自多行的表列的值连接到单个字符串中。因为在计算所有聚合字段之后,将逐个从句应用于查询结果集,所以逐个不能直接影响该字符串中的值序列。在某些情况下,XMLAGG结果可能会按顺序显示,但不应依赖此排序。给定聚合结果值中列出的值无法显式排序。

相关聚合函数

  • XMLAGG返回一个串连的值字符串。
  • LIST返回值的逗号分隔列表。
  • %DLIST返回包含每个值的元素IRIS列表。
  • JSON_ARRAYAGG返回值的JSON数组。

示例

下面的示例创建在Sample.Person表的FavoriteColors列中找到的所有不同值的串联字符串。因此,对于ALL_COLLES列,每行都有相同的值。请注意,虽然有些行的FavoriteColors为空值,但该值不包括在连接的字符串中。数据值以内部格式返回。

SELECT Name,FavoriteColors,
   XMLAGG(DISTINCT FavoriteColors) AS All_Colors_In_Table
FROM Sample.Person
ORDER BY FavoriteColors

下面的示例返回以“A”开头的Home_State值的串联字符串。它返回不同的Home_State值(不同的Home_State);与不同的Home_City值对应的Home_State值(与(Home_City)Home_State不同),其中可能包括Home_City的一个唯一NULL;以及所有Home_State值:

SELECT XMLAGG(DISTINCT Home_State) AS DistStates,
       XMLAGG(DISTINCT BY(Home_City) Home_State) AS DistCityStates,
       XMLAGG(Home_State) AS AllStates
FROM Sample.Person
WHERE Home_State %STARTSWITH 'A'

下面的示例为每个州创建在Home_City列中找到的所有不同值的串联字符串。同一州的每一行都包含该州所有不同城市值的列表:

SELECT Home_State, Home_City,
   XMLAGG(DISTINCT Home_City %FOREACH(Home_State)) AS All_Cities_In_State
FROM Sample.Person
ORDER BY Home_State

以下示例使用%AFTERHAVING关键字。它为每个包含至少一个满足HAVING子句条件(以“C”“K”开头的名称)的Name值的Home_State返回一行。第一个XMLAGG函数返回由该州的所有名称组成的连接字符串。第二个XMLAGG函数返回仅由满足HAVING子句条件的名称组成的连接字符串:

SELECT Home_State,
       XMLAGG(Name) AS AllNames,
       XMLAGG(Name %AFTERHAVING) AS HaveClauseNames
    FROM Sample.Person
    GROUP BY Home_State
    HAVING Name LIKE 'C%' OR Name LIKE 'K%' 
    ORDER BY Home_state

对于以下示例,假设我们有下表AutoClub

NameMakeModelYear
Smith,JoePontiacFirebird1971
Smith,JoeSaturnSW21997
Smith,JoePontiacBonneville1999
Jones,ScottFordMustang1966
Jones,ScottMazdaMiata2000
SELECT DISTINCT Name, XMLAGG(Make) AS String_Of_Makes
FROM AutoClub WHERE Name = 'Smith,Joe'
NameString_Of_Makes
Smith,JoePontiacSaturnPontiac
SELECT DISTINCT Name, XMLAGG(DISTINCT Make) AS String_Of_Makes
FROM AutoClub WHERE Name = 'Smith,Joe'
NameString_Of_Makes
Smith,JoePontiacSaturn
0
0 273
文章 姚 鑫 · 一月 3, 2022 4m read

第十二章 SQL聚合函数 VARIANCE, VAR_SAMP, VAR_POP

返回数据集统计方差的聚合函数。

大纲

VARIANCE([ALL | DISTINCT [BY(col-list)]] expression [%FOREACH(col-list)] [%AFTERHAVING])

VAR_SAMP([ALL | DISTINCT [BY(col-list)]] expression [%FOREACH(col-list)] [%AFTERHAVING])

VAR_POP([ALL | DISTINCT [BY(col-list)]] expression [%FOREACH(col-list)] [%AFTERHAVING])

参数

  • ALL - 可选-指定统计方差函数返回表达式中所有值的方差。 如果没有指定关键字,这是默认值。
  • DISTINCT - 可选- DISTINCT子句,指定统计方差函数返回不同(唯一)表达式值的方差。 DISTINCT可以指定BY(colo -list)子句,其中colo -list可以是单个字段,也可以是用逗号分隔的字段列表。
  • expression - 任何有效的表达式。 通常是包含要分析方差的数据值的列的名称。
  • %FOREACH(col-list) - 可选-列名或以逗号分隔的列名列表。
  • %AFTERHAVING - 可选-应用在HAVING子句中的条件。

这些函数返回NUMERIC数据类型,除非表达式是数据类型DOUBLE。 如果expressionDOUBLE,则返回DOUBLE

描述

这三个方差聚合函数在丢弃NULL值后返回表达式值的统计方差。 也就是说,从数据集的平均值变化的量,表示为一个正数。 返回值越大,值的数据集的变化就越大。 SQL还提供聚合函数来返回对应于每个方差函数的标准偏差。

在这种统计差异的推导过程中有一些细微的差异:

  • 方差:如果数据集中所有的值都有相同的值(无可变性),则返回0。 如果数据集只包含一个值(没有可能的可变性),则返回0。 如果数据集没有值,则返回NULL。

方差计算为:

(SUM(expression**2) * COUNT(expression)) - SUM(expression**2)
_____________________________________________________________
COUNT(expression) * (COUNT(expression) - 1)
  • VAR_SAMP:样本方差。 如果数据集中的所有值都具有相同的值(无可变性),则返回0。 如果数据集只包含一个值(没有可能的可变性),则返回NULL。 如果数据集没有值,则返回NULL。 使用与方差相同的变量计算。
  • VAR_POP:总体方差。 如果数据集中的所有值都具有相同的值(无可变性),则返回0。 如果数据集只包含一个值(没有可能的可变性),则返回0。 如果数据集没有值,则返回NULL

VAR_POP的计算是:

(SUM(expression**2) * COUNT(expression)) - (SUM(expression) **2)
_____________________________________________________________
(COUNT(expression) **2 )

这些方差聚合函数可以在引用表或视图的SELECT查询或子查询中使用。 它们可以在SELECT列表或HAVING子句中与普通字段值一起出现。

这些方差聚合函数不能在WHERE子句中使用。 它们不能在JOINON子句中使用,除非SELECT是子查询。

这些方差聚合函数返回数据类型NUMERIC的值,精度为36,刻度为17,除非表达式是数据类型DOUBLE,在这种情况下,函数返回数据类型DOUBLE

这些方差聚合函数通常应用于具有数值的字段或表达式。 它们将非数值值(包括空字符串("))计算为零(0)。

这些方差聚合函数忽略数据字段中的NULL值。 如果查询没有返回行,或者返回的所有行的数据字段值为NULL,则返回NULL

与所有聚合函数一样,统计方差函数可以采用一个可选的DISTINCT子句。 方差(DISTINCT col1)返回那些不同(唯一)的col1字段值的方差。 方差(DISTINCT BY(col2) col1)返回记录中col1字段值的方差,其中col2值是不同的(唯一的)。 但是请注意,不同的col2值可能包含一个单独的NULL值。

当前事务期间所做的更改

与所有聚合函数一样,方差函数总是返回数据的当前状态,包括未提交的更改,而不管当前事务的隔离级别如何。

示例

下面的示例使用方差返回 sample.employee 中雇员年龄的方差,以及由一个或多个雇员表示的不同年龄的方差:

SELECT VARIANCE(Age) AS AgeVar,VARIANCE(DISTINCT Age) AS PerAgeVar
     FROM Sample.Employee

下面的示例使用 VAR_POP 返回 sample.employee 中雇员年龄的总体差异,以及由一个或多个雇员表示的不同年龄的差异:

SELECT VAR_POP(Age) AS AgePopVar,VAR_POP(DISTINCT Age) AS PerAgePopVar
     FROM Sample.Employee
0
0 363
文章 姚 鑫 · 十二月 31, 2021 4m read

第十一章 SQL聚合函数 SUM

返回指定列值之和的聚合函数。

大纲

SUM([ALL | DISTINCT [BY(col-list)]] expression [%FOREACH(col-list)] [%AFTERHAVING])

参数

  • ALL - 可选-指定SUM返回表达式中所有值的和。 如果没有指定关键字,这是默认值。
  • DISTINCT - 可选-一个DISTINCT子句,指定SUM返回表达式中不同(唯一)值的和。 DISTINCT可以指定BY(colo -list)子句,其中colo -list可以是单个字段,也可以是用逗号分隔的字段列表。
  • expression - 任何有效的表达式。 通常是包含要求和的数据值的列的名称。
  • %FOREACH(col-list) - 可选-列名或以逗号分隔的列名列表。
  • %AFTERHAVING - 可选-应用在HAVING子句中的条件。

SUM返回与expression相同的数据类型,但有如下异常:TINYINTSMALLINTINTEGER返回的数据类型都是INTEGER

注意:SUM可以指定为聚合函数,也可以指定为窗口函数。 本参考页面描述了SUM作为聚合函数的使用。 SUM作为一个窗口函数在窗口函数概述中描述。

描述

SUM聚合函数返回表达式值的和。 通常,表达式是查询返回的多行中字段的名称(或包含一个或多个字段名称的表达式)。

SUM可以在引用表或视图的SELECT查询或子查询中使用。 SUM可以在SELECT列表或HAVING子句中与普通字段值一起出现。

SUM不能在WHERE子句中使用。 SUM不能在JOINON子句中使用,除非SELECT是子查询。

和所有聚合函数一样,SUM可以接受一个可选的DISTINCT子句。 SUM(DISTINCT col1)只汇总那些不同(唯一)的col1字段值。 SUM(DISTINCT BY(col2) col1)只汇总col2值不同(唯一)的记录中的col1字段值。 但是请注意,不同的col2值可能包含一个单独的NULL值。

数据值

对于数据类型为INTSMALLINTTINYINT的表达式,SUM返回的数据类型为INTEGER。 对于数据类型为BIGINT的表达式,SUM返回数据类型BIGINT。 对于数据类型为DOUBLE的表达式,SUM返回数据类型为DOUBLE的表达式。 对于所有其他数字数据类型,SUM返回数据类型numeric

SUM返回精度为18的值。 返回值的尺度与表达式的尺度相同,但有以下例外。 如果expression是一个数据类型为VARCHARVARBINARY的数值,则返回值的尺度为8。

默认情况下,聚合函数使用逻辑(内部)数据值,而不是显示值。

SUM通常应用于具有数值的字段或表达式。 因为只执行最小的类型检查,所以有可能(尽管很少有意义)对非数字字段调用它。 SUM计算包括空字符串(")在内的非数值值为0(0)。如果expression是数据类型VARCHAR,则返回到ODBC或JDBC的值是数据类型DOUBLE

在派生SUM聚合函数值时,数据字段中的NULL值将被忽略。 如果查询没有返回任何行,或者返回的所有行的数据字段值为NULL, SUM返回NULL

优化

SUM计算的SQL优化可以使用一个位片索引,如果这个索引是为字段定义的。

当前事务期间所做的更改

与所有聚合函数一样,SUM总是返回数据的当前状态,包括未提交的更改,而不考虑当前事务的隔离级别。

示例

在下面的例子中,美元符号($)连接到薪金数额。

下面的查询返回示例中所有员工的工资之和。 雇员数据库:

SELECT '$' || SUM(Salary) AS Total_Payroll
     FROM Sample.Employee

下面的查询使用 %AFTERHAVING必须返回所有工资的总和和每个州超过$80,000的工资的总和,其中至少有一个人的工资为> $80,000:

SELECT Home_State,
       '$' || SUM(Salary) AS Total_Payroll,
       '$' || SUM(Salary %AFTERHAVING) AS Exec_Payroll
     FROM Sample.Employee
     GROUP BY Home_State
     HAVING Salary > 80000
     ORDER BY Home_State

下面的查询返回示例中每个职位工资的总和和平均值。 雇员数据库:

SELECT Title,
       '$' || SUM(Salary) AS Total,
       '$' || AVG(Salary) AS Average
     FROM Sample.Employee
     GROUP BY Title
     ORDER BY Average

下面的查询显示了与算术表达式一起使用的SUM。 对于示例中的每个职位名称。 员工数据库,返回当前工资和工资增加10%的工资之和:

SELECT Title,
       '$' || SUM(Salary) AS BeforeRaises,
       '$' || SUM(Salary * 1.1) AS AfterRaises
     FROM Sample.Employee
     GROUP BY Title
     ORDER BY Title

下面的查询显示了使用CASE语句与逻辑表达式一起使用的SUM。 它计算所有受薪员工,并使用SUM计算所有年薪为9万美元或以上的受薪员工。

SELECT COUNT(Salary) As AllPaid, 
       SUM(CASE WHEN (Salary >= 90000)
           THEN 1 ELSE 0 END) As TopPaid
       FROM Sample.Employee
0
0 63