我在使用sqlalchemy更新表示雪花中的表的python模型时遇到问题。列之一是变量字段,当我尝试更新模型并将其保存回数据库时,雪花抱怨该值不是变量。我尝试将数据作为字典以及json字符串传递,但均无效。
模型属性定义为:
data = db.Column(snowsql.VARIANT)
snowsql是雪花雪花SQLAlchemy软件包的别名,该软件包已安装,但它似乎仅提供类型方言,而没有其他用途。
有人有这样做的经验吗?
更新:
我要添加的数据是字典的python列表:
new_data['data'] = [{'component': None, 'display_name': 'blah', 'key': None, 'row': {'display_name': 'blah', 'type': 'blah'}, 'sub_type': None, 'type': 'blah'}]
设置variant属性时执行json.dumps
new_blah = Blah(
data = json.dumps(new_data['data'])
)
结果:
表达式类型与列数据类型不匹配,期望为VARIANT,但列DATA为VARCHAR(8905)
转储产生的json:
"[{\"component\":null,\"display_name\":\"blah\",\"key\":null,\"row\":{\"display_name\":\"blah\",\"type\":\"blah\"},\"sub_type\":null,\"type\":\"blah\"}]"
或者,尝试在不执行json.dumps的情况下分配列表:
sqlalchemy.exc.ProgrammingError:(snowflake.connector.errors.ProgrammingError)252004:无:处理pyformat参数失败; 'dict'对象没有属性'replace'
答案 0 :(得分:0)
据我所知,您目前无法尝试。我遇到了同样的问题,尽管我对SQLAlchemy Custom Types颇有兴趣,但目前无法解决。
问题如下:
VARIANT
列中,您需要使用Snowflake函数PARSE_JSON
。SELECT
子句的上下文中,即您不能以INSERT ... VALUES
格式使用它(请参见Snowflake Community)我不知道有什么方法可以强制SQLAlchemy创建子查询,
以防将来发生变化,这是我走的距离:
class SnowflakeJSON(TypeDecorator):
impl = VARIANT
def process_bind_param(self, value, dialect):
return json_serialize(value)
def process_result_value(self, value, dialect):
return json_deserialize(value)
def bind_expression(self, bindparam):
return func.PARSE_JSON(bindparam, type_=self)
def copy(self, **kw):
return SnowflakeJSON()
这会生成一个查询,例如:
INSERT INTO my_table (key, data)
VALUES ('001', PARSE_JSON('{"test": "hello world"}'));
但是,根据上面的雪花社区条目,VALUES
格式不起作用,您需要使用以下格式:
INSERT INTO my_table (key, data)
SELECT '001', PARSE_JSON('{"test": "hello world"}');
作为后备,您始终可以使用将JSON对象存储为VARCHAR
的列类型:
class SnowflakeJSON(TypeDecorator):
impl = String
def process_bind_param(self, value, dialect):
return json_serialize(value)
def process_result_value(self, value, dialect):
return json_deserialize(value)
def copy(self, **kw):
return SnowflakeJSON()
这样,您显然会失去将JSON字符串存储为VARIANT
数据类型的好处。但是,即使在查询中,您也可以稍后进行解析:
SELECT PARSE_JSON(text)['test'] from my_table;