【问题标题】:Column is of type timestamp without time zone but expression is of type character列是没有时区的时间戳类型,但表达式是字符类型
【发布时间】:2015-11-26 23:42:08
【问题描述】:

我正在尝试在 Redshift 上实现 SCD2 时插入记录 但得到一个错误。

目标表的DDL是

CREATE TABLE ditemp.ts_scd2_test (
    id INT
    ,md5 CHAR(32)
    ,record_id BIGINT IDENTITY
    ,from_timestamp TIMESTAMP
    ,to_timestamp TIMESTAMP
    ,file_id BIGINT
    ,party_id BIGINT
    )

这是插入语句:

INSERT
INTO ditemp.TS_SCD2_TEST(id, md5, from_timestamp, to_timestamp)

SELECT TS_SCD2_TEST_STAGING.id
    ,TS_SCD2_TEST_STAGING.md5
    ,from_timestamp
    ,to_timestamp
FROM (
    SELECT '20150901 16:34:02' AS from_timestamp
        ,CASE 
            WHEN last_record IS NULL
                THEN '20150901 16:34:02'
            ELSE '39991231 11:11:11.000'
            END AS to_timestamp
        ,CASE 
            WHEN rownum != 1
                AND atom.id IS NOT NULL
                THEN 1
            WHEN atom.id IS NULL
                THEN 1
            ELSE 0
            END AS transfer
        ,stage.*
    FROM (
        SELECT id
        FROM ditemp.TS_SCD2_TEST_STAGING
        WHERE file_id = 2
        GROUP BY id
        HAVING count(*) > 1
        ) AS scd2_count_ge_1
    INNER JOIN (
        SELECT row_number() OVER (
                PARTITION BY id ORDER BY record_id
                ) AS rownum
            ,stage.*
        FROM ditemp.TS_SCD2_TEST_STAGING AS stage
        WHERE file_id IN (2)
        ) AS stage
        ON (scd2_count_ge_1.id = stage.id)
    LEFT JOIN (
        SELECT max(rownum) AS last_record
            ,id
        FROM (
            SELECT row_number() OVER (
                    PARTITION BY id ORDER BY record_id
                    ) AS rownum
                ,stage.*
            FROM ditemp.TS_SCD2_TEST_STAGING AS stage
            )
        GROUP BY id
        ) AS last_record
        ON (
                stage.id = last_record.id
                AND stage.rownum = last_record.last_record
                )
    LEFT JOIN ditemp.TS_SCD2_TEST AS atom
        ON (
                stage.id = atom.id
                AND stage.md5 = atom.md5
                AND atom.to_timestamp > '20150901 16:34:02'
                )
    ) AS TS_SCD2_TEST_STAGING
WHERE transfer = 1

简而言之,我正在尝试将20150901 16:34:02 插入到from_timestamp39991231 11:11:11.000to_timestamp

得到

ERROR: 42804: column "from_timestamp" is of type timestamp without time zone but expression is of type character varying

谁能建议如何解决这个问题?

【问题讨论】:

    标签: postgresql amazon-redshift


    【解决方案1】:

    Postgres 没有将 20150901 16:34:02(您的输入)识别为有效的时间/日期格式,因此它假定它是一个字符串。

    改用标准日期格式,最好是 ISO-8601。 2015-09-01T16:34:02

    SQLFiddle example

    【讨论】:

      【解决方案2】:

      以防万一有人最终在这里尝试从准备好的语句中的 groovy 或 Java 中的变量插入 timestamptimestampz 并得到相同的错误(就像我一样),我设法通过将属性stringtype 设置为"unspecified" 来实现。根据documentation

      指定绑定PreparedStatement参数集时使用的类型 通过 setString()。如果 stringtype 设置为 VARCHAR(默认值),例如 参数将作为 varchar 参数发送到服务器。如果 stringtype 设置为未指定,参数将被发送到 服务器作为无类型值,服务器将尝试推断 合适的类型。如果您有现有的应用程序,这将很有用 它使用 setString() 来设置实际上是其他的参数 类型,例如整数,并且您无法更改应用程序 使用适当的方法,例如 setInt()。

      Properties props = [user : "user", password: "password", 
      driver:"org.postgresql.Driver", stringtype:"unspecified"]
      def sql = Sql.newInstance("url", props)
      

      使用此属性集,您可以将时间戳作为字符串变量插入,而不会出现问题标题中引发的错误。例如:

      String myTimestamp= Instant.now().toString()
      sql.execute("""INSERT INTO MyTable (MyTimestamp) VALUES (?)""",
      [myTimestamp.toString()]
      

      这样,postgresql 可以正确推断时间戳的类型(来自字符串)。我希望这会有所帮助。

      【讨论】:

      • 帮助了我。谢谢。
      【解决方案3】:

      在apache-tomcat-9.0.7/conf/server.xml里面

      在 url 地址末尾添加“?stringtype=unspecified”。 例如:

      <GlobalNamingResources> 
      <Resource name="jdbc/??" auth="Container" type="javax.sql.DataSource"
             ...
             url="jdbc:postgresql://127.0.0.1:5432/Local_DB?stringtype=unspecified"/>
      </GlobalNamingResources>
      

      【讨论】:

        猜你喜欢
        • 2019-11-08
        • 2021-06-18
        • 2020-02-17
        • 2015-11-09
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 2021-12-27
        • 2020-12-28
        相关资源
        最近更新 更多