从Sequel准备插入ID

时间:2011-08-23 18:35:21

标签: ruby oracle jruby sequel

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

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

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

prepared_statement.call :value=>'Some value'

我有一个触发器和一个序列设置,因此ID将自动生成。我想回到我刚刚添加的行(或id),但我看不清楚如何。 我无法使用insert因为值是CLOB且可能超过4000个字符。

3 个答案:

答案 0 :(得分:1)

在JRuby中,使用JDBC适配器可以覆盖insert并传入returns子句。棘手的部分是你并不总是知道这个级别的主键是什么,所以你可能不得不使用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]传递,但我可能记错了。

这是一个可以完成工作的负载kludge。将它专门化为Oracle JDBC适配器并确保从原始execute语句中提供所有错误处理代码会更优雅。考虑到我希望得到更好的东西并将其送回续集项目​​的时间。

答案 1 :(得分:0)

获取填充序列值的方法是通过INSERT的RETURNING子句 我在本回复中讨论to a similar question regarding CodeIgniter

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

答案 2 :(得分:0)

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