1

我在 Sequel 中有一个准备好的插入语句(使用 Oracle)。

prepared_statement = DB[:table_name].prepare(:insert, :name, :value=>:$value)

当我调用它时,该行被添加得很好。

prepared_statement.call :value=>'Some value'

我有一个触发器和一个序列设置,所​​以 ID 将自动生成。我想取回刚刚添加的行(或 id),但我不知道如何取回。我不能使用insert,因为 value 是 CLOB 并且可能大于 4000 个字符。

4

3 回答 3

1

在 JRuby 中,使用 JDBC 适配器可以覆盖插入并传入返回子句。棘手的部分是您并不总是知道此级别的主键是什么,因此您可能必须使用 ROWID 或请求返回所有列。

您最终会得到类似于以下内容的内容:

module Sequel
  module JDBC
    class Database
      def execute_insert_with_returning(conn, sql, opts = {})        
        columns = opts[:key_columns] || ["ROWID"]
        q = "{ call #{sql} returning #{columns.join(',')} into #{columns.collect {|_| '?'}.join(',')} }"
        stmt = conn.prepare_call(q)
        raise "Unable to prepare call for insert" if stmt.nil?

        begin
          columns.each_with_index do |_, index|
            stmt.registerOutParameter(index+1, JavaSQL::Types::VARCHAR)
          end
          return nil if 0 == stmt.executeQuery

          values = (1..columns.count).inject({}) do |memo, index|
            key = columns[index-1].downcase.to_sym rescue nil
            memo[key] = stmt.get_string(index) unless key.nil?
            memo
          end
          values
        ensure
          stmt.close
        end
      end # #execute_insert_with_returning

      alias execute_without_specialized_insert execute
      def execute(sql, opts={}, &block)
        if opts[:type] == :insert
          synchronize(opts[:server]) do |conn|
            execute_insert_with_returning conn, sql, opts
          end
        else
          execute_without_specialized_insert sql, opts, &block
        end
      end # #execute
    end # Database
  end # JDBC
end # Sequel

我已经做了类似这样的事情,而且效果很好。我认为我们还必须覆盖 Sequel::Model 以便它将主键作为 opts[:key_columns] 传递,但我可能记错了。

这是一个完成工作的承重杂物。将其专门用于 Oracle JDBC 适配器并确保所有错误处理代码都来自原始执行语句会更优雅。考虑到时间,我很想得到更好的东西并将其归还给 Sequel 项目。

于 2011-09-16T13:53:46.283 回答
0

获取填充序列值的方法是通过 INSERT 语句的 RETURNING 子句,正如我在对有关 CodeIgniter 的类似问题的回复中所讨论的那样。

我不确定 RoR 的基本版本是否支持该语法,但似乎可以扩展 ActiveRecord 来处理它。了解更多

于 2011-08-23T21:31:09.977 回答
0

Sequel 的 Oracle 适配器不支持本机预准备语句,因此它回退到发出常规查询。如果您可以使用 JRuby,那么 jdbc 适配器具有本机准备好的语句支持,因此它应该可以在那里工作。如果您不能使用 JRuby,您将不得不努力向 Oracle 适配器添加本地准备好的语句支持。我无权访问 Oracle 安装,因此无法测试任何支持,但如果您遇到问题,我很乐意提供建议。

于 2011-08-24T17:10:46.180 回答