第三十一章 SQL函数 CONVERT

第三十一章 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 codes Four-digit year codes Format
  0 or 100 Mon dd yyyy hh:mmAM (or PM)
1 101 mm/dd/yy
2 102 yy.dd.mm
3 103 dd/mm/yy
4 104 dd.mm.yy
5 105 dd-mm-yy
6 106 dd Mon yy
7 107 Mon dd, yy (no leading zero when dd < 10)
  8 or 108 hh:mm:ss
  9 or 109 Mon dd yyyy hh:mm:ss:nnnAM (or PM)
10 110 mm-dd-yy
11 111 yy.mm.dd
12 112 yymmdd
  13 or 113 dd Mon yyyy hh:mm:ss:nnn (24 hour)
  14 or 114 hh:mm:ss.nnn (24 hour)
  20 or 120 yyyy-mm-dd hh:mm:ss (24 hour)
  21 or 121 yyyy-mm-dd hh:mm:ss.nnnn (24 hour)
  126 yyyy-mm-ddThh:mm:ss,nnnn (24 hour)
  130 dd Mon yyyy hh:mm:ss:nnnAM (or PM)
  131 dd/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的数据类型转换。
在下表中,有两组转换数据类型,第一组转换数据值和数据类型,第二组转换数据类型,但不转换数据值:

Source Conversion
Any numeric data type SQL_VARCHAR, SQL_DOUBLE, SQL_DATE, SQL_TIME
%String SQL_DATE, SQL_TIME, SQL_TIMESTAMP
%Date SQL_VARCHAR, SQL_POSIXTIME, SQL_TIMESTAMPSQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT, SQL_DATE
%Time SQL_VARCHAR, SQL_POSIXTIME, SQL_TIMESTAMP SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT,SQL_SMALLINT, SQL_TINYINT, SQL_TIME
%PosixTime SQL_TIMESTAMP, SQL_DATE, SQL_TIME SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
%TimeStamp SQL_POSIXTIME, SQL_DATE, SQL_TIME SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
Any non-stream data type SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
Any non-stream data type SQL_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
image.png

下面的示例将字符流字段转换为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
image.png

默认格式和代码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
image.png

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

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

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

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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容