【问题标题】:SQL compilation error: Expression type does not match column data type, expecting TIMESTAMP_NTZ(9) but got TIMESTAMP_LTZ(9) for column CREATE_DTSQL 编译错误:表达式类型与列数据类型不匹配,应为 TIMESTAMP_NTZ(9) 但为列 CREATE_DT 获得了 TIMESTAMP_LTZ(9)
【发布时间】:2020-03-17 17:07:15
【问题描述】:

问题:用于 CREATE TABLE 的正确 DDL 是什么...DEFAULT...CURRENT_TIMESTAMP()

我有一个 CREATE 或 REPLACE 语句,它对 CREATE_DT 列使用 DEFAULT - 当有人将数据插入表中时,当前服务器日期/时间应填充该列

CREATE OR REPLACE TABLE "EDW_ADMIN"."ETL_SPROC_LOG" (   
   "ETL_SPROC_LOG_ID" NUMBER IDENTITY NOT NULL, 
   "OBJECT_NAME" VARCHAR2(250 CHAR) NOT NULL, 
   "LOG_ENTRY" VARCHAR2(1000 CHAR) NOT NULL, 
   "DYNAMIC_SQL" VARCHAR2(10000 CHAR) NULL,
   "DURATION" NUMBER NULL,
   "ROWS_AFFECTED" NUMBER NULL,
   "ERROR_CODE" VARCHAR2(200 CHAR) NULL, 
   "ERROR_DESC" VARCHAR2(4000 CHAR) NULL, 
   "CREATE_DT" TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
   "CREATE_USER" VARCHAR2(50) NOT NULL DEFAULT CURRENT_USER()
);

当我们从列中检索数据时,我们将使用以下内容将系统日期/时间更改为我们的时区。

ALTER SESSION SET TIMEZONE = 'AMERICA/NEW_YORK';

当我们执行一个像这样的示例插入语句时,我们得到一个错误:

   INSERT INTO edw_admin.ETL_SPROC_LOG (OBJECT_NAME, LOG_ENTRY) VALUES ('OBJ', 'ENTRY1');

SQL compilation error: Expression type does not match column data type, expecting TIMESTAMP_NTZ(9) but got TIMESTAMP_LTZ(9) for column CREATE_DT

用于定义 DEFAULT CURRENT_TIMESTAMP() 的正确 DDL 是什么?我们是否需要在创建语句将时区设置为 NTZ(9) 之前更改 DDL 脚本中的会话?我认为 Snowflake 在不同的时区有多个服务器,因此系统时间将取决于服务器的位置。

雪花文档说

返回系统的当前时间戳。 https://docs.snowflake.net/manuals/sql-reference/functions/current_timestamp.html

它没有参数来控制它返回的时区。

Snowflake 文档中的此页面暗示了 CONVERT_TIMEZONE(source_tz, target_tz, source_timestamp_ntz) 的使用,但同样,如果我们是不同的时区,具体取决于执行 DEFAULT 的服务器,我认为这也会失败。

https://docs.snowflake.net/manuals/sql-reference/functions/convert_timezone.html

【问题讨论】:

  • 如果您不关心时区,请使用 NTZ,这需要您将 current_timestamp() 转换为 timestamp_ntz。但是,我认为根据您的问题,您确实希望它是 timestamp_ltz,但您想将时区保存为“America/New_York”。帐户默认值通常基于您的 Snowflake 帐户所在的位置,但您始终可以更改它。日期始终以 UTC 格式存储。您能否更清楚您希望 current_timestamp() 位于哪个时区,以及您希望用户在从不同时区查询时如何查看该时区?

标签: create-table snowflake-cloud-data-platform


【解决方案1】:

我认为问题在于TIMESTAMP 数据类型默认为TIMESTAMP_NTZ,除非您设置Parameter TIMESTAMP_TYPE_MAPPING = TIMESTAMP_LTZ

由于CURRENT_TIMESTAMP() 产生TIMESTAMP_LTZ 值,因此数据类型不匹配。

这似乎有效:

CREATE OR REPLACE TABLE TM (
  V NUMBER,
  T TIMESTAMP DEFAULT CURRENT_TIMESTAMP::TIMESTAMP
);
INSERT INTO TM(V) VALUES(12345);
SELECT * FROM TM;

V       T
12345   2019-11-21 19:03:57.098

【讨论】:

  • 确实,将 CURRENT_TIMESTAMP 转换为时间戳会使错误消失,但是存储在数据库中的值没有时区,因此您无法真正判断何时插入记录。最好将 TimeZone 附加到表中的数据,因此下面的答案(以及 Snowflake 在 Inforomatoin Schema 中使用的内容 - 列的数据类型设置为 TIMESTAMP_LTZ(9))
  • 如果你用TIMESTAMP_NTZ来存储UTC就可以了,但我个人总是用TIMESTAMP_LTZ...
【解决方案2】:

答案:使用数据类型 TIMESTAMP_LTZ(9) 代替列的 DDL 的时间戳(见下文)

为了让日期/时间以您会话所在的格式返回,必须将其存储在表中,并将一列定义为本地时区值,然后使用 ALTER SESSION 稍后选择它。这就是信息架构中的对象存储时间戳的方式 - 数据类型为 TIMESTAMP_LTZ(9)。

这是最终代码和结果

CREATE OR REPLACE TABLE "EDW_ADMIN"."ETL_SPROC_LOG" (   
   "ETL_SPROC_LOG_ID" NUMBER IDENTITY NOT NULL, 
   "OBJECT_NAME" VARCHAR2(250 CHAR) NOT NULL, 
   "LOG_ENTRY" VARCHAR2(1000 CHAR) NOT NULL, 
   "DYNAMIC_SQL" VARCHAR2(10000 CHAR) NULL,
   "DURATION" NUMBER NULL,
   "ROWS_AFFECTED" NUMBER NULL,
   "ERROR_CODE" VARCHAR2(200 CHAR) NULL, 
   "ERROR_DESC" VARCHAR2(4000 CHAR) NULL, 
   "CREATE_DT" TIMESTAMP_LTZ(9) DEFAULT CURRENT_TIMESTAMP(),
   "CREATE_USER" VARCHAR2(50) NOT NULL DEFAULT CURRENT_USER()
);

-- Unit test the new tables identity column and defaults
INSERT INTO edw_admin.ETL_SPROC_LOG (OBJECT_NAME, LOG_ENTRY) VALUES ('OBJ', 'ENTRY1');

ALTER SESSION SET TIMEZONE = 'America/New_York';
select create_dt from etl_sproc_log;
    2019-11-21 15:04:50.108 -0500

ALTER SESSION SET TIMEZONE = 'America/Los_Angeles';
select create_dt from etl_sproc_log;
    2019-11-21 12:04:50.108 -0800

ALTER SESSION SET TIMEZONE = 'GMT';
select create_dt from etl_sproc_log;
    2019-11-21 20:04:50.108 +0000

ALTER SESSION UNSET TIMEZONE;
select create_dt from etl_sproc_log;
    2019-11-21 12:04:50.108 -0800


truncate table edw_admin.etl_sproc_log;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 2023-03-15
    • 2018-03-31
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多