0

我正在尝试使用 Java + Hibernate 将数据从 RedShift 卸载到 S3,但无法弄清楚如何让它接受 SQL 中的字符串中的字符串。

无论我尝试使用转义序列来将引号字符正确传递给 RedShift,我都会在异常之后得到异常。

任何想法都会受到欢迎。谢谢。

这是我试图在 RedShift 上运行的查询(如果我直接在 RedShift 中输入它,它可以工作):

unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\' ')
  to 's3://myBucket/myTable/'
  credentials 'aws_access_key_id=*;aws_secret_access_key=*' gzip;

以下是我在 Java 中尝试过的各种命令,但遇到了错误:

单反斜杠

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

结果
警告 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL 错误:0,SQLState:42601
错误 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 错误:“2013”​​位置或附近的语法错误位置:66
错误 org .hibernate.exception.SQLGrammarException:无法执行语句

双反斜杠

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \\'2013-01-01\\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

结果
错误org.hibernate.QueryException:参数前缀':' [unload('select raw_line from stl_load_errors where starttime > \'2013-01-01\'')到's3://myBucket/myTable/ '凭证'aws_access_key_id=*;aws_secret_access_key=*'gzip]
在 org.hibernate.engine.query.spi.ParameterParser.parse(ParameterParser.java:95)

三重反斜杠

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \\\'2013-01-01\\\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

结果
2013-06-19 01:39:59,233 错误 org.hibernate.QueryException:参数前缀 ':' [unload ('select raw_line from stl_load_errors where starttime > \'2013-01-01\'')到 's3://myBucket/myTable/' 凭据 'aws_access_key_id=*;aws_secret_access_key=*' gzip]
到 org.hibernate.engine.query.spi.ParameterParser.parse(ParameterParser.java:95)

四反斜杠

session.createSQLQuery("unload ('select raw_line from stl_load_errors where starttime > \\\\'2013-01-01\\\\' ')"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .executeUpdate();

结果
警告 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL 错误:0,SQLState:42601
错误 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 错误:“2013”​​位置或附近的语法错误:68
错误组织.hibernate.exception.SQLGrammarException:无法执行语句

命名参数

session.createSQLQuery("unload (:query)"
  + " to 's3://myBucket/myTable/'"
  + " credentials 'aws_access_key_id=" + key + ";aws_secret_access_key=" + secret + "'  gzip")
  .setString("query", "select raw_line from stl_load_errors where starttime > '2013-01-01'")
  .executeUpdate();

结果:
警告 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL 错误:0,SQLState:42601
错误 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 错误:“$1”位置或附近的语法错误:9
错误org.hibernate.exception.SQLGrammarException:无法执行语句

4

2 回答 2

1

你应该看看美元引用的字符串:

http://www.postgresql.org/docs/current/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING

于 2013-06-20T09:00:59.033 回答
0

有人建议我尝试将 s3 路径作为命名参数,因为 Hibernate(在双反斜杠和三重反斜杠情况下)似乎不喜欢冒号字符。

这样做,给了我这个错误:

错误 java.lang.IllegalArgumentException:参数 s3 不作为命名参数存在于 [unload ('select raw_line from stl_load_errors where starttime > \'2014-01-01\'') 到 :s3 credentials 'aws_access_key_id=*;aws_secret_access_key= *' 压缩包]

我的印象是 Hibernate 对转义的单引号感到困惑,并且忘记了应该引用的内容和不应该引用的内容(s3 之后的冒号首先不应该造成问题,因为它在里面引用的文本,但显然 Hibernate 无法弄清楚)。

有时你离问题太近了。在没有考虑一段时间之后,明显的解决方案(实际上是解决方法)是我将执行以下操作:

  1. 创建临时表
  2. 将需要的数据插入到临时表中(不需要嵌套字符串)
  3. 将临时表的全部内容卸载到 S3(不需要嵌套字符串)
  4. 删除临时表
于 2013-06-19T13:43:24.500 回答