如何让SQLAlchemy在创建Netezza表时仅使用TIMESTAMP类型而非默认的TIMESTAMP WITHOUT TIME ZONE
解决SQLAlchemy to_sql创建Netezza表时TIMESTAMP类型报错的问题
我之前也踩过Netezza这个语法兼容的坑——它确实不支持TIMESTAMP WITHOUT TIME ZONE这种标准SQL写法,只认单纯的TIMESTAMP。而SQLAlchemy(哪怕用了nzalchemy)在生成DDL时会自动给TIMESTAMP/DATETIME类型加上WITHOUT TIME ZONE后缀,刚好触发了Netezza的语法错误。
下面给你几个可行的解决方案:
方案1:自定义Netezza兼容的TIMESTAMP类型
这个方法针对单个字段生效,灵活可控:
首先定义一个继承自SQLAlchemy TypeDecorator的自定义类型,覆盖它的列定义生成逻辑:
from sqlalchemy.types import TypeDecorator, TIMESTAMP from sqlalchemy import VARCHAR, NVARCHAR class NetezzaTimestamp(TypeDecorator): impl = TIMESTAMP cache_ok = True # 标记该类型可缓存,提升性能 def get_col_spec(self, **kw): # 直接返回Netezza支持的TIMESTAMP语法 return "TIMESTAMP"
然后在你的数据类型字典里替换原来的TIMESTAMP:
import nzalchemy targetDATATYPES = { 'LAB': VARCHAR(100), 'feed_start_date': NetezzaTimestamp(), # 用自定义类型替代原生TIMESTAMP 'file_name': VARCHAR(100), 'curr_hash_sum': nzalchemy.NUMERIC(15, 2), 'fact_table_name': NVARCHAR(100) }
这样当to_sql生成CREATE TABLE语句时,feed_start_date对应的类型就会是TIMESTAMP,而不是带后缀的版本,Netezza就能正常执行了。
方案2:全局修改Netezza方言的类型映射
如果你的项目里有很多TIMESTAMP字段需要处理,全局修改方言的类型映射会更高效:
from sqlalchemy.dialects.netezza.base import NetezzaDialect from sqlalchemy.types import TIMESTAMP, DATETIME # 覆盖TIMESTAMP和DATETIME的默认列定义 NetezzaDialect.colspecs[TIMESTAMP] = lambda *args, **kwargs: "TIMESTAMP" NetezzaDialect.colspecs[DATETIME] = lambda *args, **kwargs: "TIMESTAMP" # Netezza里DATETIME和TIMESTAMP等效,也可以改成"DATETIME"
执行这段代码后,整个项目中所有用TIMESTAMP/DATETIME的字段,生成DDL时都会自动输出TIMESTAMP,不用逐个修改字段类型。
验证效果
修改后,to_sql生成的CREATE语句会变成这样:
CREATE TABLE "xxx"."[targetTableName]" ( lab NVARCHAR(100), feed_start_date TIMESTAMP, file_name NVARCHAR(100), curr_hash_sum NUMERIC(15, 2), fact_table_name NVARCHAR(100) ) DISTRIBUTE ON RANDOM
这个语句在Netezza里就能正常执行了。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

