草庐IT

postgresql - 如何将参数传递给用 PL/pgSQL 编写的查询?

coder 2024-07-05 原文

我想知道是否可以将参数传递给用 PL/pgSQL 编写的查询?

我试过了,但是失败了 pq: got 1 parameters but the statement requires 0

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "host=localhost dbname=db user=user sslmode=disable password=pw")
    if err != nil {
        log.Fatal(err)
    }
    row := db.QueryRow(`
DO $$
BEGIN
    IF true THEN
        SELECT $1;
    END IF;
END$$
`, 1)
    var num int
    err = row.Scan(&num)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(num)
}

另一个相关的问题是我想使用事务,但是sql包提供的API似乎每次在tx中执行查询时都会连接到db。如果可能的话,我希望一次性执行所有操作。例如,在 go 中你应该使用这样的事务

tx, err := db.Begin()
rows, err := tx.Query(sql1)
result, err := tx.Exec(sql2)
tx.Commit()

问题是,如果我没记错的话,调用 tx.Querytx.Exec 会两次访问 PostgreSQL 服务器。我想要实现的是合并 sql1sql2,将它们包装在 BEGINEND 中并在其中执行一次旅行。我的问题是:

  1. 您认为有必要吗?我想如果有足够的流量,性能差异可能会很明显,但我不确定。
  2. 如果是这样,执行此合并交易的最佳方式是什么?创建一个函数并在 PL/pgSQL 中运行事务(因为我可能需要使用条件语句等)?

最佳答案

你得到错误是因为 PL/pgSQL 应该在服务器端定义为 functionprocedure,但在你的情况下,它是从客户端调用的。下面是一个关于如何定义和调用带有参数的函数的简单示例:

CREATE OR REPLACE FUNCTION myadd(a integer, b integer) RETURNS integer AS $$
    BEGIN
            RETURN a + b;
    END;
$$ LANGUAGE plpgsql;

然后,您可以从客户端使用 SELECT 查询调用带参数的函数。请注意,即使您的函数包含 INSERT/UPDATE,也必须使用 SELECT 语句调用该函数。

//...
a := 10
row := db.QueryRow(`SELECT * FROM myadd($1, $2)`, a, 130)
//...

下一个问题,关于事务和 PL/pgSQL。是的,使用 PL/pgSQL 可以减少网络流量。 Several advantages服务器端语言 (PL/pgSQL) 是:

  1. 消除客户端-服务器往返
  2. 无需将中间结果传输给客户端,只会传输最终结果。
  3. 避免多次解析查询(向服务器发送查询 --> 服务器解析查询 --> 执行数据库操作 --> 返回结果给客户端等...)

处理数据库(大数据)的规则是你需要避免移动你的数据,PL/pgSQL 符合这个规则。然而,有些情况下你不能(需要避免)使用 PL/pgSQL,例如数据库管理员/服务器所有者不允许服务器端编程(安全/性能原因等)。

functiontransaction 之间的关系在the manual 中有明确说明。 :

It is important not to confuse the use of BEGIN/END for grouping statements in PL/pgSQL with the similarly-named SQL commands for transaction control. PL/pgSQL's BEGIN/END are only for grouping; they do not start or end a transaction. Functions and trigger procedures are always executed within a transaction established by an outer query — they cannot start or commit that transaction, since there would be no context for them to execute in. However, a block containing an EXCEPTION clause effectively forms a subtransaction that can be rolled back without affecting the outer transaction

总而言之,使用 PL/pgSQL 您可能会获得性能提升。多少?是依赖。请记住,使用 PL/pgSQL 后,您需要管理多个代码库,有时很难调试。

关于postgresql - 如何将参数传递给用 PL/pgSQL 编写的查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43608002/

有关postgresql - 如何将参数传递给用 PL/pgSQL 编写的查询?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  9. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐