清除过滤器
文章
姚 鑫 · 一月 22, 2022
# 第三十一章 SQL函数 CONVERT
将给定表达式转换为指定数据类型的函数。
```java
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`)时,如果字符数据类型(如`CHAR`或`VARCHAR`)没有指定长度,则默认的最大长度为`30`个字符。
如果二进制数据类型(如`binary`或`VARBINARY`)没有指定长度,则默认的最大长度为`30`个字符。
否则,这些没有指定长度的数据类型将被映射到一个`1`个字符的`MAXLEN`,如`data types`表所示。
可以执行`BIT`数据类型转换。
允许的值为`1`、`0`或`NULL`。
如果指定任何其他值,IRIS将发出`SQLCODE -141`错误。
在下面的嵌入式SQL示例中,两者都是一个`NULL`的`BIT`转换:
```java
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`。
- 默认值:
- 将时间值转换为`TIMESTAMP`、`POSIXTIME`、`DATETIME`或`SMALLDATETIME`时,日期默认为`1900-01-01`。
注意,对于`{fn CONVERT()}`,日期默认为`1841-01-01`。
- 将日期值转换为`TIMESTAMP`、`POSIXTIME`、`DATETIME`或`SMALLDATETIME`时,时间默认为`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/109`、`13/113`、`14/114`、`130和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 `Time`、`Timestamp`或`Date`表示。
- 当将时间值转换为`SQL_TIMESTAMP`或`SQL_POSIXTIME`时,未指定的日期默认为`1841-01-01`。
注意,对于`CONVERT()`,日期默认为`1900-01-01`。
- 将`date`值转换为`SQL_TIMESTAMP`或`SQL_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_VARCHAR`和`SQL_TIMESTAMP`返回提供的值。
- 数字数据类型转换为`0`(零)。
- `SQL_DATE`和`SQL_TIME`转换为`NULL`。
# CONVERT 类方法
还可以使用`CONVERT()`方法调用执行数据类型转换,使用" `SQL_ `"关键字指定数据类型:
```java
$SYSTEM.SQL.Functions.CONVERT(expression,convert-to-type,convert-from-type)
```
如下示例所示:
```java
WRITE $SYSTEM.SQL.CONVERT(60945,"SQL_VARCHAR","SQL_DATE")
2007-11-11
```
# 示例
## CONVERT() 示例
下面的示例使用标量语法形式的`CONVERT`。
下面的示例比较了使用`DECIMAL`和`DOUBLE`数据类型对小数的转换:
```sql
SELECT CONVERT(DECIMAL,-123456789.0000123456789) AS DecimalVal,
CONVERT(DOUBLE,-123456789.0000123456789) AS DoubleVal
```
下面的示例将字符流字段转换为`VARCHAR`文本字符串。
它还使用`CHAR_LENGTH`显示字符流字段的长度:
```sql
SELECT Notes,CONVERT(VARCHAR(80),Notes) AS NoteText,CHAR_LENGTH(Notes) AS TextLen
FROM Sample.Employee WHERE Notes IS NOT NULL
```
下面的例子展示了几种将出生日期字段(`DOB`)转换为格式化字符串的方法:
```sql
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`字段不包含时间值,所以显示时间的格式(这里包括默认值`10`0、`114`和`126`)提供一个零值,它表示`12:00AM`(午夜)。
代码`126`格式提供了一个不包含空格的日期和时间字符串。
## {fn CONVERT()} 示例
下面的示例使用了`ODBC`语法形式的`CONVERT`。
下面的嵌入式SQL示例将混合字符串转换为整数。
IRIS在第一个非数字字符处截断字符串,然后将结果数字转换为规范形式:
```java
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
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQLCommand).Convert1()
SQLCODE=0
the host variable is:7
```
下面的示例将`“DOB”`(出生日期)列中的日期转换为`SQL_TIMESTAMP`数据类型。
```sql
SELECT DOB,{fn CONVERT(DOB,SQL_TIMESTAMP)} AS DOBtoTstamp
FROM Sample.Person
```
生成的时间戳格式为`“yyyy-mm-dd hh:mm:ss”`。
下面的示例将`“DOB”`(出生日期)列中的日期转换为`SQL_INTEGER`数据类型。
```sql
SELECT DOB,{fn CONVERT(DOB,SQL_INTEGER)} AS DOBtoInt
FROM Sample.Person
```
下面的示例将`“DOB”`(出生日期)列中的日期转换为`SQL_VARCHAR`数据类型。
```sql
SELECT DOB,{fn CONVERT(DOB,SQL_VARCHAR)} AS DOBtoVChar
FROM Sample.Person
```
生成的字符串格式为:`yyyy-mm-dd`。
文章
TZ Zhuang · 六月 2, 2021
InterSystems产品有四种备份方法:(1) 外部备份(2) 在线备份(3) 冷备份(4) 传统的并行外部备份有关这些方法的细节请参考在线文档 https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GCDI_BACKUP
以下是对每种备份方法的简要描述:
(1) 外部备份外部备份是InterSystems推荐的最佳备份方式。外部备份一般是对数据库文件所在的存储创建快照的方式来实现。创建快照可以在多个层面进行,例如存储层面,操作系统层面,等等,因此这些相关技术和工具一般由第三方来提供。在做快照前,一定要先停止对数据库文件的写入(InterSystems IRIS的IRIS.DAT,Caché/Ensemble的CACHE.DAT)。但是用户进程可以继续对内存进行更新,而不需要中断。InterSystems提供了停止对数据库文件写入的方法,用户可以把这个加入到快照工具的脚本里。外部备份一般包括以下几步:1. 使用Backup.General.ExternalFreeze()方法来停止对数据库文件的写入。2. 使用第三方快照工具来对文件系统创建快照。3. 使用Backup.General.ExternalThaw()方法来恢复对数据库文件的写入。4. 把快照拷贝到备份介质上(用于存储备份的磁盘,磁带,等等)。5. 删除快照。
(2) 在线备份在线备份是InterSystems自己特有的备份方式,可实现无宕机备份。但是,在线备份只能备份数据库文件(InterSystems IRIS的IRIS.DAT,Caché/Ensemble的CACHE.DAT),并且会把所有需要备份的数据库文件中的数据块写入到一个.cbk的备份文件。因此如果想要使用在线备份来备份整个系统环境,除了数据库文件外,还需要额外备份很多系统文件,例如InterSystems产品的安装目录,WIJ文件,主日志和备日志目录等等。在线备份包括3种类型:1. 全备份 -- 把所有使用的数据块写入到一个.cbk文件。2. 累积备份 -- 从上一次全备份起,所有变化过的数据块写入到一个.cbk文件。恢复时,需要和上一次全备份一起恢复。3. 增量备份 -- 从上一次备份起,所有变化过的数据块写入到一个.cbk文件。恢复时,需要和上一次全备份及中间所有备份一起恢复。在线备份的这些特性,并不适用于作为数据量大的生产系统的备份方案。
(3) 冷备份冷备份是在数据库系统正常停机状态下,所做的外部备份,即拷贝文件系统到存储介质。
(4) 传统的并行外部备份传统的并行外部备份是一种在特殊情况下才可行的备份方法。一般需要满足以下条件:1. 数据库在一个集群里,并且不能有宕机时间。2. 没有快照功能。3. 在线备份不能满足需求。并行外部备份结合了数据库文件(*.DAT)拷贝和在线备份里增量备份的功能。其步骤如下:1. 在数据库中设置备份启动标志。2. 拷贝数据库文件(*.DAT)。3. 对该拷贝时间内被修改的数据进行在线备份的增量备份。具体使用情况和详情也请参考在线文档 https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=GCDI_backup#GCDI_backup_methods_ext_concurrent
最新版本InterSystems IRIS for Health示例:===============================================================1. 设置标志,开始备份数据库。Set ^ClearOK=$CLRINC^DBACK("QUIET")2. 拷贝操作系统上的数据库文件(*.DAT)。3. 运行下面的命令,表明你已经使用了一个外部备份工具。Set x=$$BACKUP^DBACK("","E","Dirty external backup","","","")4. 进行增量备份。Set x=$$BACKUP^DBACK("","I","incremental","test.cbk","Y","bck.log","QUIET","Y","Y")===============================================================InterSystems产品中的上述处理可以做成例程Routine或类方法,并与批处理相结合进行操作。关于传统并行外部备份中使用的^DBACK例程的更多信息,请参考以下文件https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=GCDI_backup#GCDI_backup_util_DBACK_entry_backup