在插入 postgres 之前截断 table
Truncating table before insert in postgres
我正在尝试创建一种机制,每次调用插入命令时都会截断 tables。
首先,我尝试创建一个获取行数组并在插入行之前截断 table 的函数:
CREATE OR REPLACE FUNCTION insert_customers(customers customer[])
RETURNS VOID AS
$$
BEGIN
TRUNCATE TABLE Customers;
INSERT INTO Customers (CustomerID, CustomerName) SELECT * FROM UNNEST(customers::Customer[]);
END
$$
LANGUAGE plpgsql;
其中 Customer 是用户定义的类型,表示 Customers table 中的一行:
CREATE TYPE Customer AS (
customerid VARCHAR(100),
customername VARCHAR(100));
当我从 psql 调用函数时,它起作用了:
SELECT * FROM insert_customers(ARRAY[ROW('ID1', 'Name1'),ROW('ID2', 'Name2')]::Customer[]);
但我还没有找到从我的 java 代码执行此插入的方法:
String[][] customers = new String[2][];
customers[0] = new String[] { "ID1", "Name1" };
customers[1] = new String[] { "ID2", "Name2" };
Array sqlArray = connection.createArrayOf("customer", customers);
CallableStatement cstmt = connection.prepareCall("{ call insert_customers(?) }");
cstmt.setArray(1, sqlArray);
cstmt.execute();
创建了以下语句:
select * from insert_customers ('{{"ID1", "Name1"},{"ID2", "Name2"}}') as result
并抛出以下异常:
org.postgresql.util.PSQLException: ERROR: malformed record literal: "ID1"\n Detail: Missing left parenthesis.
然后我尝试创建一个触发器,它将在插入事件时截断 table:
CREATE TRIGGER on_insert_customers
BEFORE INSERT ON Customers
EXECUTE PROCEDURE truncate_customers();
其中truncate_customers是:
CREATE OR REPLACE FUNCTION truncate_customers()
RETURNS TRIGGER AS
$$
BEGIN
TRUNCATE TABLE Customers;
END
$$
LANGUAGE plpgsql;
这引发了异常:
cannot TRUNCATE "customers" because it is being used by active queries in this session
有什么想法吗???
修改函数
查询未嵌套文本数组的元素对:
select cols[1], cols[2]
from (
select (ordinality- 1)/2, array_agg(unnest) cols
from unnest('{"id1", "name1", "id2", "name2"}'::text[]) with ordinality
group by 1
) s
cols | cols
------+-------
id1 | name1
id2 | name2
(2 rows)
在您的函数中使用它,以便它可以将文本数组作为参数:
create or replace function insert_customers(text[])
returns void language plpgsql as $$
begin
truncate table customers;
insert into customers (customerid, customername)
select cols[1], cols[2]
from (
select (ordinality- 1)/2, array_agg(unnest) cols
from unnest() with ordinality
group by 1
) s;
end $$;
select insert_customers('{"id1", "name1", "id2", "name2"}');
修改触发函数
您不能在触发器中截断 table,但您可以删除所有行:
...
delete from Customers;
return new;
...
我正在尝试创建一种机制,每次调用插入命令时都会截断 tables。
首先,我尝试创建一个获取行数组并在插入行之前截断 table 的函数:
CREATE OR REPLACE FUNCTION insert_customers(customers customer[])
RETURNS VOID AS
$$
BEGIN
TRUNCATE TABLE Customers;
INSERT INTO Customers (CustomerID, CustomerName) SELECT * FROM UNNEST(customers::Customer[]);
END
$$
LANGUAGE plpgsql;
其中 Customer 是用户定义的类型,表示 Customers table 中的一行:
CREATE TYPE Customer AS (
customerid VARCHAR(100),
customername VARCHAR(100));
当我从 psql 调用函数时,它起作用了:
SELECT * FROM insert_customers(ARRAY[ROW('ID1', 'Name1'),ROW('ID2', 'Name2')]::Customer[]);
但我还没有找到从我的 java 代码执行此插入的方法:
String[][] customers = new String[2][];
customers[0] = new String[] { "ID1", "Name1" };
customers[1] = new String[] { "ID2", "Name2" };
Array sqlArray = connection.createArrayOf("customer", customers);
CallableStatement cstmt = connection.prepareCall("{ call insert_customers(?) }");
cstmt.setArray(1, sqlArray);
cstmt.execute();
创建了以下语句:
select * from insert_customers ('{{"ID1", "Name1"},{"ID2", "Name2"}}') as result
并抛出以下异常:
org.postgresql.util.PSQLException: ERROR: malformed record literal: "ID1"\n Detail: Missing left parenthesis.
然后我尝试创建一个触发器,它将在插入事件时截断 table:
CREATE TRIGGER on_insert_customers
BEFORE INSERT ON Customers
EXECUTE PROCEDURE truncate_customers();
其中truncate_customers是:
CREATE OR REPLACE FUNCTION truncate_customers()
RETURNS TRIGGER AS
$$
BEGIN
TRUNCATE TABLE Customers;
END
$$
LANGUAGE plpgsql;
这引发了异常:
cannot TRUNCATE "customers" because it is being used by active queries in this session
有什么想法吗???
修改函数
查询未嵌套文本数组的元素对:
select cols[1], cols[2]
from (
select (ordinality- 1)/2, array_agg(unnest) cols
from unnest('{"id1", "name1", "id2", "name2"}'::text[]) with ordinality
group by 1
) s
cols | cols
------+-------
id1 | name1
id2 | name2
(2 rows)
在您的函数中使用它,以便它可以将文本数组作为参数:
create or replace function insert_customers(text[])
returns void language plpgsql as $$
begin
truncate table customers;
insert into customers (customerid, customername)
select cols[1], cols[2]
from (
select (ordinality- 1)/2, array_agg(unnest) cols
from unnest() with ordinality
group by 1
) s;
end $$;
select insert_customers('{"id1", "name1", "id2", "name2"}');
修改触发函数
您不能在触发器中截断 table,但您可以删除所有行:
...
delete from Customers;
return new;
...