【问题标题】:TinyTds::Error: Procedure expects parameterTinyTds::Error: 过程需要参数
【发布时间】:2015-03-25 18:31:06
【问题描述】:

给定以下红宝石:

    sql2 = 'SELECT (CASE WHEN freq = 0 THEN \'pass\' ELSE \'fail\' END) FROM ( 
SELECT COUNT(*) freq FROM Grant_Award WHERE Grant_Award.org_ticker IS NULL )x;'
    pp ActiveRecord::Base.connection.select_all(sql2)

    sql1 = "SELECT (CASE WHEN freq = 0 THEN 'pass' ELSE 'fail' END) FROM ( SELECT COUNT(*) freq FROM Grant_Award WHERE Grant_Award.org_ticker IS NULL )x;"
    pp ActiveRecord::Base.connection.select_all(sql1)

    sql0 = File.readlines(File.join(BASE,'db','scripts','test','pass_or_fail.sql'))
    sql = (sql0.map {|l| l.strip}).join(' ')
    pp sql
    pp ActiveRecord::Base.connection.select_all(sql)

以上产生以下结果:

#<ActiveRecord::Result:0x38b0ce0
 @column_types={},
 @columns=[""],
 @hash_rows=nil,
 @rows=[["pass"]]>

#<ActiveRecord::Result:0x38b5ae0
 @column_types={},
 @columns=[""],
 @hash_rows=nil,
 @rows=[["pass"]]>

"SELECT (CASE WHEN freq = 0 THEN 'pass' ELSE 'fail' END) FROM ( SELECT COUNT(*) freq FROM Grant_Award WHERE Grant_Award.org_ticker IS NULL )x;"

C:/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-sqlserver-adapter-4.2.2/lib/active_record/connection_adapters/sqlserver/database_statements.rb:336:in `each': TinyTds::Error: Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'.: EXEC sp_executesql 'SELECT (CASE WHEN freq = 0 THEN ''pass'' ELSE ''fail'' END) FROM ( SELECT COUNT(*) freq FROM Grant_Award WHERE Grant_Award.org_ticker IS NULL )x;' (ActiveRecord::StatementInvalid)

执行 sql 的前两次尝试都返回正常。第三个,从文件中读取到数组中,然后加入,炸弹。我知道这一定与字符串的处理有关。但我想不通。

我做错了什么?为什么它(tinytds 或 activerecord?)认为这是一个存储过程?

我想做的是在一个文件夹里放一大堆sql脚本,然后一个一个地执行。

详细信息:ruby 1.9.3、activerecord (4.2.0) 和 tiny_tds (0.6.2-x86-mingw32)

【问题讨论】:

  • 语句末尾的 x 是做什么的?这对我来说看起来不对。

标签: ruby sql-server activerecord tiny-tds


【解决方案1】:

我今天早上醒来,意识到这一定与磁盘上文件的字符集有关。以下是[不更改查询]的解决方案:

ActiveRecord::Base.connection.select_all(sql0.join(" ").encode("UTF-8"))

我在提交时将字符集强制为utf-8,现在一切正常。

证明:

#<ActiveRecord::Result:0x3bede68
 @column_types={},
 @columns=[""],
 @hash_rows=nil,
 @rows=[["pass"]]>

#<ActiveRecord::Result:0x3bf2c68
 @column_types={},
 @columns=[""],
 @hash_rows=nil,
 @rows=[["pass"]]>

"SELECT (CASE WHEN freq = 0 THEN 'pass' ELSE 'fail' END) FROM ( SELECT COUNT(*) freq FROM Grant_Award WHERE Grant_Award.org_ticker IS NULL )x;"

#<ActiveRecord::Result:0x3bf5410
 @column_types={},
 @columns=[""],
 @hash_rows=nil,
 @rows=[["pass"]]>

【讨论】:

    【解决方案2】:

    我认为文件导入生成的语句应该是:

    SELECT (CASE WHEN freq = 0 THEN 'pass' ELSE 'fail' END) FROM ( SELECT COUNT(*) freq FROM Grant_Award WHERE Grant_Award.org_ticker IS NULL );"
    

    我认为语句末尾的 x 导致了错误,并想知道这是否错误地滑入了您的其他行。

    【讨论】:

    • TSql 需要子查询的标签。没有标签的 Sql Server 会抛出错误。我使用小写的“x”来使其在视觉上显得低调,并且不会分散其他代码的注意力,因为标签在此查询中在功能上是无用的。
    • 啊!我通常会在子查询和 x 之间放置一个 AS。
    • 我在这里和那里学习一点点,因为我以前不需要处理代码页。代码中的字符串 sql2 或 sql1 采用 US-ASCII 编码。从文件 sql0 中读取的字符串编码为 IBM437。我不确定 IBM437 是否是典型的,但这是我的笔记本电脑的配置方式。当我将代码页强制为 UTF-8 时,一切都很好。
    • 我尝试将“encoding: utf-8”添加到我的 database.yml 中,希望 activerecord/tinytds 能够接受它并在内部进行转换,但没有骰子。我必须明确强制更改代码。
    • 要添加一个挑剔的评论。可以从我的问题中删除 -1 吗?我真的认为这个问题和解决方案是值得注意的,我不希望有人忽略这篇文章,因为他们可能会从中受益。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多