相关疑难解决方法(0)

在PL/pgSQL函数中选择或执行

我在我的数据库中有这个功能:

CREATE OR REPLACE FUNCTION "insertarNuevoArticulo"(nombrearticulo character varying, descripcion text, idtipo integer, idfamilia bigint, artstock integer, minstock integer, maxstock integer, idmarca bigint, precio real, marcastock integer)
RETURNS boolean AS
$BODY$
DECLARE
    articulo "Articulo"%ROWTYPE;
BEGIN
    SELECT * INTO articulo FROM "Articulo" WHERE "Nombre" = $1 AND "idTipo"=$3 AND "idFamilia"=$4;
    IF NOT FOUND THEN
        INSERT INTO "Articulo" ("Nombre", "Descripcion", "idTipo", "idFamilia", "Stock", "MinStock", "MaxStock") Values ($1, $2, $3, $4, $5, $6, $7);
        SELECT last_value
        INTO articulo."idArticulo"
        FROM "public"."Articulo_idArticulo_seq";
    END IF;
    SELECT * …
Run Code Online (Sandbox Code Playgroud)

postgresql function plpgsql select-into

11
推荐指数
1
解决办法
3万
查看次数

处理PostgreSQL中的竞争条件

我有几个工作者,每个工作者都拥有自己与PostgreSQL的连接.工人们操纵着不同的桌子.

工作人员处理来自系统外部的并行请求.正在访问的表之一是用户表.当一些信息出现时,我首先需要确保表中的用户有一条记录.如果没有记录,我希望首先创建一个.

我正在使用以下成语:

if [user does not exist] then [create user]
Run Code Online (Sandbox Code Playgroud)

代码[user does not exist]是:

SELECT id FROM myschema.users WHERE userId='xyz'
Run Code Online (Sandbox Code Playgroud)

我测试是否返回任何行.

(简化)代码[create user]是:

INSERT INTO myschema.users VALUES ('xyz')
Run Code Online (Sandbox Code Playgroud)

当我的系统处理有关同一用户的不同信息的并行流时,我经常会收到PostgreSQL错误:

Key (id)=(xyz) already exists
Run Code Online (Sandbox Code Playgroud)

之所以发生这种情况是因为该SELECT命令不返回任何行,然后另一个工作程序创建用户,任何我的工作程序都尝试执行相同操作,从而导致示例性并发错

根据PostgreSQL文档,默认情况下,每当我隐式启动一个事务时,只要我不提交它,表就会被锁定.我没有使用自动提交,我只在块中提交事务,例如在整个if-else块之后.

实际上,我可以if-else直接将这些东西放入SQL中,但它并不能解决我的锁定问题.我假设"赢家全部使用"范例将起作用,并且设法执行SELECT命令的第一个工作人员将拥有锁,直到它调用COMMIT.

我在SO上已经阅读了很多不同的主题,但我仍然不确定什么是正确的解决方案.我应该使用显式锁定表,因为隐式锁定不起作用?我怎样才能确保只有一个工人拥有一张桌子?

sql postgresql concurrency multithreading locking

11
推荐指数
2
解决办法
4663
查看次数

如果存在行则返回id,否则返回INSERT

我正在node.js中编写一个函数来查询PostgreSQL表.
如果该行存在,我想从该行返回id列.
如果它不存在,我想插入它并返回id(insert into ... returning id).

我一直在尝试变体caseif else语句,似乎无法让它发挥作用.

sql postgresql node.js sql-insert

10
推荐指数
2
解决办法
7283
查看次数

禁止"重复键值违反唯一约束"错误

我正在开发一个使用Postgres作为其数据库的Rails 3应用程序.我有下面的表格:

             Table "public.test"
    Column     |  Type   | Modifiers
---------------+---------+-----------
 id            | integer | not null
 some_other_id | integer |
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)
    "some_other_id_key" UNIQUE CONSTRAINT, btree (some_other_id)
Run Code Online (Sandbox Code Playgroud)

这有两列:

  • id,这是主键(由rails自动创建)
  • some_other_id,包含由另一个系统生成的密钥.这个id必须是唯一的,所以我在表中添加了一个唯一的键约束.

现在如果我尝试插入一个带有重复的行some_other_id,它会失败(好)并且我在Postgres日志中得到以下输出:

ERROR:  duplicate key value violates unique constraint "some_other_id_key"
Run Code Online (Sandbox Code Playgroud)

问题是,我的应用程序尝试添加相同的ID两次是完全主线,并且我的日志被这个"错误"消息垃圾邮件,这会导致各种问题:文件占用大量磁盘空间,诊断会丢失噪音,Postgres必须丢弃diags以保持日志文件的大小限制等.

有谁知道我怎么做:

  • 通过禁止有关此键的所有日志,或者通过在尝试执行此操作的事务上指定某些内容来抑制日志INSERT.
  • 使用其他一些Postgres功能来发现重复的键,而不是尝试INSERT.我听说过规则和触发器,但是我无法工作(虽然我不是Postgres专家).

请注意,任何解决方案都需要使用Rails,它执行如下插入:

INSERT INTO test (some_other_id) VALUES (123) RETURNING id;
Run Code Online (Sandbox Code Playgroud)

sql postgresql ruby-on-rails duplicates sql-insert

8
推荐指数
1
解决办法
1万
查看次数

如何仅在不存在的情况下创建记录,避免重复并且不会引发任何错误?

众所周知,Model.find_or_create_by(X)实际上:

  1. 由X选择
  2. 如果找不到 - >由X创建
  3. 返回记录(找到或创建)

在步骤1和2之间可能存在争用条件.为了避免数据库中的X重复,应该在X的字段集上使用唯一索引.但是如果应用唯一索引,那么竞争事务之一将失败异常(尝试创建X的副本时).

如何实现"安全版本",#find_or_create_by它永远不会引发任何异常并始终按预期工作?

postgresql transactions ruby-on-rails upsert rails-activerecord

8
推荐指数
1
解决办法
5834
查看次数

从条件INSERT中获取Id

对于像这样的表:

CREATE TABLE Users(
    id SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);
Run Code Online (Sandbox Code Playgroud)

以下操作的正确单一查询插入是什么:

给定用户name,插入新记录并返回新记录id.但如果name已经存在,只需返回id.

我知道PostgreSQL 9.5中的新语法ON CONFLICT(column) DO UPDATE/NOTHING,但我无法弄清楚,如果有的话,它可以提供帮助,因为我需要id返回.

这似乎RETURNING idON CONFLICT不属于一起.

sql postgresql concurrency upsert

8
推荐指数
1
解决办法
1893
查看次数

找不到PostgreSQL过程语言"C"

我试图在PostgreSQL 9.2数据库中使用PL/R过程语言.我已经安装了该plr语言,我正在尝试将其添加到数据库中.当我运行该命令时,CREATE EXTENSION plr;我收到以下错误:

ERROR:  language "C" does not exist
STATEMENT:  CREATE EXTENSION plr;
ERROR:  language "C" does not exist
Run Code Online (Sandbox Code Playgroud)

当我列出数据库中的可用语言时,select * from pg_language;我得到了

 lanname  | lanowner | lanispl | lanpltrusted | lanplcallfoid | laninline | lanvalidator | lanacl 
 ----------+----------+---------+--------------+---------------+-----------+--------------+--------
  internal |       10 | f       | f            |             0 |         0 |         2246 | 
  c        |       10 | f       | f            |             0 |         0 |         2247 | 
  sql      |       10 | …
Run Code Online (Sandbox Code Playgroud)

postgresql stored-procedures capitalization keyword plr

7
推荐指数
1
解决办法
6359
查看次数

INSERT-SELECT查询是否可以受竞争条件的影响?

我有这个查询,balances如果表中不存在相应的行,则尝试向表中添加行totals.使用PostgreSQL上的默认隔离级别在事务中运行查询.

INSERT INTO balances (account_id, currency, amount)
SELECT t.account_id, t.currency, 0
FROM balances AS b
RIGHT OUTER JOIN totals USING (account_id, currency) AS t
WHERE b.id IS NULL
Run Code Online (Sandbox Code Playgroud)

我有一个UNIQUE约束balances (accountId, currency).我担心如果多个会话同时执行此查询,我将陷入竞争状态,导致重复键错误.我已经看过很多关于这个问题的问题,但它们似乎都涉及子查询,多个查询或pgSQL函数.

由于我没有在我的查询中使用任何这些,它是否没有竞争条件?如果不是我该如何解决?

sql postgresql race-condition

6
推荐指数
1
解决办法
550
查看次数

如何尝试多个 SELECT 直到获得结果?

如果我想以递减精度搜索表中的单行,例如:

SELECT * FROM image WHERE name LIKE 'text' AND group_id = 10 LIMIT 1
Run Code Online (Sandbox Code Playgroud)

如果这没有给我结果,请尝试这个:

SELECT * FROM image WHERE name LIKE 'text' LIMIT 1
Run Code Online (Sandbox Code Playgroud)

当这没有给我结果时,尝试这个:

SELECT * FROM image WHERE group_id = 10 LIMIT 1
Run Code Online (Sandbox Code Playgroud)

是否可以只用一种表达方式来做到这一点?

当我没有两个而是例如三个或更多搜索参数时,也会出现问题。有通用的解决方案吗?当然,当搜索结果按相关性排序时,它会派上用场。

sql postgresql union postgresql-performance

5
推荐指数
1
解决办法
792
查看次数

PL/pgSQL列名与变量相同

我是plpgsql的新手,我正在尝试创建一个函数来检查表中是否存在某个值,如果不存在则会添加一行.

CREATE OR REPLACE FUNCTION hire(
    id_pracownika integer,
    imie character varying,
    nazwisko character varying,
    miasto character varying,
    pensja real)
  RETURNS TEXT AS
$BODY$
DECLARE
wynik TEXT;
sprawdzenie INT;
BEGIN
sprawdzenie = id_pracownika;
IF EXISTS (SELECT id_pracownika FROM pracownicy WHERE id_pracownika=sprawdzenie) THEN
wynik = "JUZ ISTNIEJE";
RETURN wynik;
ELSE
INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (id_pracownika,imie,nazwisko,miasto,pensja);
wynik = "OK";
RETURN wynik;   
END IF;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
Run Code Online (Sandbox Code Playgroud)

问题是我收到错误,说这id_pracownika是一个列名和一个变量.

如何在这种上下文中指定"id_pracownika"是指列名?

postgresql plpgsql uniqueidentifier race-condition

5
推荐指数
1
解决办法
4383
查看次数