从 Sequel 准备中获取插入的 ID

发布于 2024-11-30 22:38:00 字数 370 浏览 0 评论 0原文

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

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

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

prepared_statement.call :value=>'Some value'

我设置了一个触发器和一个序列,以便自动生成 ID。我想取回我刚刚添加的行(或 id),但我不知道如何做。 我无法使用 insert,因为值是 CLOB 并且可能超过 4000 个字符。

I have a prepared insert statement in Sequel (using Oracle).

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

When I call it the row gets added just fine.

prepared_statement.call :value=>'Some value'

I have a trigger and a sequence set up so the ID will be auto generated. I would like to get back the row (or the id) I just added, but I can't see how. I can't use insert because value is a CLOB and may be greater than 4000 characters.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苦行僧 2024-12-07 22:38:00

在 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 适配器并确保所有错误处理代码都来自原始执行语句会更加优雅。如果有时间的话,我很想得到更好的东西并将其回馈给续集项目。

In JRuby, using the JDBC adapter you can override the insert and pass in the returning clause. The tricky part is that you don't always know what the primary key is at this level so you may have to use ROWID or request all of the columns back.

You end up with something that looks similar to this:

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

I've done something pretty much like this and it works pretty good. I think we had to override the Sequel::Model as well so it passes the primary key in as opts[:key_columns] but I may be remembering incorrectly.

This is a bit of a load bearing kludge that gets the job done. It would be more elegant to specialize it to the Oracle JDBC adapter and to ensure that all of the error handling code is present from the original execute statement. Given the time I'd love to get something better and give it back to the Sequel project.

乜一 2024-12-07 22:38:00

获取填充序列值的方法是通过 INSERT 的 RETURNING 子句
声明,正如我在此回复中讨论的 有关 CodeIgniter 的类似问题

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

The way to get the populated sequence values is through the RETURNING clause of the INSERT
statement, as I discuss in this response to a similar question regarding CodeIgniter.

I'm not sure whether the base version of RoR supports that syntax, but it appears to be possible to extend ActiveRecord to handle it. Find out more.

再见回来 2024-12-07 22:38:00

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

Sequel's Oracle adapter doesn't have native prepared statement support, so it falls back to issuing a regular query. If you can use JRuby, the jdbc adapter has native prepared statement support, so it should just work there. If you can't use JRuby, you'll have to work on adding native prepared statement support to the Oracle adapter. I don't have access to an Oracle installation, so I can't test any support, but I'll be happy to provide advice if you run into problems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文