gpt4 book ai didi

postgresql - 如何从已执行的准备语句中获取 $1 参数的值(在使用 current_query() 的触发器内)

转载 作者:行者123 更新时间:2023-11-29 11:25:05 27 4
gpt4 key购买 nike

在一个触发器中我想看看是什么sql查询触发了这个触发器。我使用了 postgresql (8.4) 的 current_query() 函数。

一切都很好,但是如果触发器是由准备好的语句执行的,我会得到占位符 ($1) 而不是正确的值。例如(记录查询):

delete from some_table where id=$1

有没有办法获取/拥有这些值/参数?

已编辑(添加示例):

--table for saving query
create table log_table (
query text
)

--table for trigger
create table some_table (
id text
)
--function itself
CREATE FUNCTION save_query() RETURNS trigger AS $$
switch $TG_op {
DELETE {
spi_exec "INSERT INTO log_table (query) VALUES (current_query())"
}
default {
return OK
}
}
return OK
$$ LANGUAGE pltcl;

创建触发器:

create trigger test_trigger before delete on some_table for each row execute procedure save_query();

准备好的语句从休眠中执行。

再次编辑(添加了java部分)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class DeleteUsingPreparedStmt {

public static void main(String[] args) {
try {
String deleteString = "delete from floors where id = ? ";
final int idToDelte = 1;

Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://127.0.0.1:5432/YOUR_DATABASE";
Connection conn = DriverManager.getConnection(url, "user", "password");

PreparedStatement deleteStmt = conn.prepareStatement(deleteString);
deleteStmt.setInt(1, idToDelte);
deleteStmt.executeUpdate();
} catch (Exception e) {
//hide me :)
}
}
}

您需要一个 jdbc 驱动程序 - click .

最佳答案

这是一些工作代码(对于 Debian 用户:只需安装 postgresql-pltcl-8.4 包并运行 CREATE LANGUAGE pltcl;)

CREATE TABLE log_table (
id serial,
query text
);

CREATE TABLE floors (
id serial,
value text
);

INSERT INTO floors(value) VALUES ('aaa'), ('bbb');

CREATE OR REPLACE FUNCTION save_query() RETURNS trigger AS $$
switch $TG_op {
DELETE {
spi_exec "INSERT INTO log_table (query) VALUES (current_query())"
}
default {
return OK
}
}
return OK
$$ LANGUAGE pltcl;

CREATE TRIGGER test_trigger
BEFORE DELETE ON floors
FOR EACH ROW
EXECUTE PROCEDURE save_query();

但是我无法在准备好的语句中获取占位符(它返回 EXECUTE deleteFromFloors(2);):

TABLE log_table;
id | query
----+-------
(0 rows)
DELETE FROM floors WHERE id = 1;
DELETE 1
TABLE log_table;
id | query
----+----------------------------------
1 | DELETE FROM floors WHERE id = 1;
(1 row)
PREPARE deleteFromFloors(integer) AS
DELETE FROM floors WHERE id = $1;
PREPARE
EXECUTE deleteFromFloors(2);
DELETE 1
TABLE log_table;
id | query
----+----------------------------------
1 | DELETE FROM floors WHERE id = 1;
2 | EXECUTE deleteFromFloors(2);
(2 rows)

编辑:

解决方法是使用 OLD 记录(在 Tcl 中表示为数组),从那里获取 id 列并使用 replace函数来代替 $1。这里有两个解决方案:PL/pgSQL 和 PL/Tcl:

CREATE OR REPLACE FUNCTION save_query() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO log_table (query)
VALUES (replace(current_query(), '$1', OLD.id::text));
RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION save_query() RETURNS trigger AS $$
switch $TG_op {
DELETE {
spi_exec "INSERT INTO log_table (query)
VALUES (replace(current_query(), '\$1', '$OLD(id)'))"
}
default {
return OK
}
}
return OK
$$ LANGUAGE pltcl;

结果:

java -classpath '.:postgresql-8.4-702.jdbc4.jar' DeleteUsingPreparedStmt

TABLE log_table;
id | query
----+---------------------------------
1 | delete from floors where id = 1

(1 行)

关于postgresql - 如何从已执行的准备语句中获取 $1 参数的值(在使用 current_query() 的触发器内),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7107237/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com