SSMS调用Snowflake的OPENQUERY时报SQL命令未正确结束错误
报错原因
这个异常是Snowflake ODBC驱动与SQL Server OPENQUERY的元数据协商缺陷导致的,和你写的SQL语法本身没有关系:
- OPENQUERY的执行逻辑是SQL Server将第二个参数中的查询语句原封不动发送给远程数据源(Snowflake)执行,拿到结果后再处理外层的别名、过滤、列选择逻辑。
- 当你外层查询直接写
select *或者只写S.*时,SQL Server向Snowflake请求结果集元数据的请求会触发旧版Snowflake ODBC驱动的解析bug,驱动会在发送给Snowflake的SQL末尾拼接非法字符,导致Snowflake侧检测到语法错误,返回SQL command not properly ended报错。 - 你测试的
SELECT S.col_1,S.col_2,*写法能正常运行,是因为这种写法下SQL Server的元数据请求逻辑不会触发该驱动bug,查询可以正常解析执行。
解决办法
你可以任选以下一种方案修复问题:
- 方案1:避免在外层查询单独使用
S.*或者全量*,要么显式写出所有需要查询的列名,要么保留一个冗余列声明和*搭配使用,示例:
SELECT -- 写一个任意存在的列当冗余声明,后面跟*即可正常执行 S.col_1 ,* FROM OPENQUERY ( [xxx], 'SELECT * FROM schema.table_a' ) as S where S.[col_1] = 'whatever';
- 方案2:把所有查询逻辑放到OPENQUERY内部执行,不需要在SQL Server侧做列选择和过滤,示例:
select * from OPENQUERY ( [xxx], 'SELECT * FROM schema.table_a WHERE col_1 = ''whatever''' ) as S
注意字符串参数在OPENQUERY的查询字符串里需要用两个单引号转义。
- 方案3:升级你SSMS所在机器安装的Snowflake ODBC驱动到2.25.x及以上的最新版本,该bug已经在新版驱动中被修复,升级后即可正常使用
S.*的写法。
内容的提问来源于stack exchange,提问作者Chicken Sandwich No Pickles
相关产品推荐
相关产品推荐

