Postgres:为什么在将char列修改为时间戳时会出现输入语法错误?

时间:2016-06-12 21:47:03

标签: sql database postgresql

我将数据从csv复制到我的表中。但是,时间戳数据与表中的列一起复制为char(40)。现在我想修改表以将其作为时间戳,但不断收到指定输入语法错误的错误。

我相信数据的格式为ISO8601

e.g。 2016-06-03T08:00:00.020584124-04:00

我已经尝试了两个具有相同结果的SQL语句

ALTER TABLE public.data
    ALTER COLUMN timestamp TYPE TIMESTAMP WITH TIME ZONE USING timestamp::TIMESTAMP WITH TIME ZONE;

ALTER TABLE public.data
   ALTER COLUMN timestamp TYPE TIMESTAMPTZ USING timestamp::TIMESTAMPTZ;

更新:当我使用psycopg2的copy_from时,它会读取标题值。这就解释了为什么我在尝试更改任何char()值时遇到问题。一旦我使用copy_expert并指定csv包含头文件,我就可以使用TIMESTAMPTZ数据类型。

4 个答案:

答案 0 :(得分:0)

您需要括号来支持冒号(def word_list_to_lower(words): """ takes a word list with a special order (e.g. frequency) returns a new word list all in lower case with no uniques but preserving order""" print("word_list_to_lower") # save orders in a dict orders = dict() for i in range(len(words)): wl = words[i].lower() # save index of first occurence of the word (prioritizing top value) if wl not in orders: orders[wl] = i # contains unique lower case words, but in wrong order words_unique = list(set(map(str.lower, words))) # reconstruct sparse list in correct order words_lower = [''] * len(words) for w in words_unique: i = orders[w] words_lower[i] = w # remove blank entries words_lower = [s for s in words_lower if s!=''] return words_lower )语法)或者您应该稍微改变它:

::

由于ALTER TABLE public.data ALTER COLUMN "timestamp" TYPE TIMESTAMP WITH TIME ZONE USING TIMESTAMP WITH TIME ZONE "timestamp"; 是保留字,我建议您以不同的方式命名字段。

答案 1 :(得分:0)

我首先编写一个select语句,将数据正确转换为时间戳。     从数据

中选择x,y,z,to_timestamp(时间戳,'格式')

定义格式的地方https://www.postgresql.org/docs/current/static/functions-formatting.html

然后只需添加一个     创建表data_new为 在您的选择查询前面

最后删除表数据并重命名新表

答案 2 :(得分:0)

首先,将列命名为#34;时间戳"这是一个非常糟糕的主意。因为它是类型的保留名称。

USING子句中,您可以提供一个表达式,用于计算旧列的新列值。您只需执行默认的简单赋值转换timestamp::TIMESTAMPTZ

应该是这样的:

ALTER TABLE public.data
    ALTER COLUMN "timestamp" TYPE TIMESTAMP WITH TIME ZONE
    USING to_timestamp("timestamp", 'YYYY-MM-DD HH:MI:SS');

问题是你有纳秒无法解析。您可以将其解析为微秒(添加US:YYYY-MM-DD HH:MI:SS US),但它会给您带来不好的结果。以下是数据类型格式化函数的documentation

如果你可以省略微秒,那就没问题了。但如果没有,您应该编写自己的解析函数并在USING子句中使用它。

答案 3 :(得分:0)

您的ALTER语句都可以。您认为这些值是ISO8601,但也有一些不是。您可以尝试使用regexp找到它们,例如:

select *
from public.data
where regexp_replace (timestamp, '\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{9}-\d\d:\d\d', '') <> ''

顺便说一句,将timestamp作为列名称是个坏主意。