相关疑难解决方法(0)

Postgres:INSERT如果不存在

我正在使用Python写入postgres数据库:

sql_string = "INSERT INTO hundred (name,name_slug,status) VALUES ("
sql_string += hundred + ", '" + hundred_slug + "', " + status + ");"
cursor.execute(sql_string)
Run Code Online (Sandbox Code Playgroud)

但由于我的一些行是相同的,我收到以下错误:

psycopg2.IntegrityError: duplicate key value  
  violates unique constraint "hundred_pkey"
Run Code Online (Sandbox Code Playgroud)

如何编写'INSERT除非此行已存在'SQL语句?

我见过这样的复杂陈述:

IF EXISTS (SELECT * FROM invoices WHERE invoiceid = '12345')
UPDATE invoices SET billed = 'TRUE' WHERE invoiceid = '12345'
ELSE
INSERT INTO invoices (invoiceid, billed) VALUES ('12345', 'TRUE')
END IF
Run Code Online (Sandbox Code Playgroud)

但首先,这对于我需要的东西是否过度,其次,我怎样才能将其中一个作为简单的字符串执行?

python postgresql sql-insert

304
推荐指数
10
解决办法
27万
查看次数

使用空列创建唯一约束

我有一个这种布局的表:

CREATE TABLE Favorites
(
  FavoriteId uuid NOT NULL PRIMARY KEY,
  UserId uuid NOT NULL,
  RecipeId uuid NOT NULL,
  MenuId uuid
)
Run Code Online (Sandbox Code Playgroud)

我想创建一个类似于此的唯一约束:

ALTER TABLE Favorites
ADD CONSTRAINT Favorites_UniqueFavorite UNIQUE(UserId, MenuId, RecipeId);
Run Code Online (Sandbox Code Playgroud)

但是,这将允许多行具有相同的(UserId, RecipeId)if MenuId IS NULL.我想允许NULLMenuId存储不具有关联菜单中的最爱,但我只希望每个用户/食谱对这些行中最多只有一个.

我到目前为止的想法是:

  1. 使用一些硬编码的UUID(例如全零)而不是null.
    但是,MenuId每个用户的菜单都有一个FK约束,所以我必须为每个用户创建一个特殊的"空"菜单,这是一个麻烦.

  2. 使用触发器检查是否存在空条目.
    我认为这是一个麻烦,我喜欢尽可能避免触发器.另外,我不相信他们能保证我的数据永远不会处于不良状态.

  3. 只需忘记它并检查中间件或插入函数中是否存在空条目,并且没有此约束.

我正在使用Postgres 9.0.

我有什么方法可以忽略吗?

sql postgresql null database-design referential-integrity

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

在ON CONFLICT子句中使用多个conflict_target

我在表中两列col1,col2他们都是独一无二的索引(COL1是唯一的,因此是COL2).

我需要插入到这个表中,使用ON CONFLICT语法并更新其他列,但我不能同时使用两个列in conflict_target子句.

有用:

INSERT INTO table
...
ON CONFLICT ( col1 ) 
DO UPDATE 
SET 
-- update needed columns here
Run Code Online (Sandbox Code Playgroud)

但是如何为几个列执行此操作,如下所示:

...
ON CONFLICT ( col1, col2 )
DO UPDATE 
SET 
....
Run Code Online (Sandbox Code Playgroud)

postgresql upsert postgresql-9.5

70
推荐指数
4
解决办法
4万
查看次数

使用Postgres一次在3个表中插入数据

我想通过一个查询将数据插入到3个表中.
我的表如下所示:

CREATE TABLE sample (
   id        bigserial PRIMARY KEY,
   lastname  varchar(20),
   firstname varchar(20)
);

CREATE TABLE sample1(
   user_id    bigserial PRIMARY KEY,
   sample_id  bigint REFERENCES sample,
   adddetails varchar(20)
);

CREATE TABLE sample2(
   id      bigserial PRIMARY KEY,
   user_id bigint REFERENCES sample1,
   value   varchar(10)
);
Run Code Online (Sandbox Code Playgroud)

我将获得一个密钥以换取每次插入,我需要在下一个表中插入该密钥.
我的查询是:

insert into sample(firstname,lastname) values('fai55','shaggk') RETURNING id;
insert into sample1(sample_id, adddetails) values($id,'ss') RETURNING user_id;
insert into sample2(user_id, value) values($id,'ss') RETURNING id;
Run Code Online (Sandbox Code Playgroud)

但是,如果我运行单个查询,他们只是向我返回值,我不能立即在下一个查询中重用它们.

怎么做到这一点?

sql postgresql common-table-expression sql-insert sql-returning

64
推荐指数
4
解决办法
4万
查看次数

在一个命令中选择或插入一行

我正在使用PostgreSQL 9.0,我有一个只有一个人工密钥(自动递增序列)和另一个唯一密钥的表.(是的,这个表有一个原因.:))我想通过另一个键查找一个ID,如果它不存在,则插入它:

SELECT id
FROM mytable
WHERE other_key = 'SOMETHING'
Run Code Online (Sandbox Code Playgroud)

然后,如果没有匹配:

INSERT INTO mytable (other_key)
VALUES ('SOMETHING')
RETURNING id
Run Code Online (Sandbox Code Playgroud)

问题:是否可以通过在一个语句中执行这两个操作来保存到DB的往返?如果它不存在,我可以插入行:

INSERT INTO mytable (other_key)
SELECT 'SOMETHING'
WHERE NOT EXISTS (SELECT * FROM mytable WHERE other_key = 'SOMETHING')
RETURNING id
Run Code Online (Sandbox Code Playgroud)

...但是这不会给出现有行的ID.有任何想法吗?如果有帮助,对other_key有一个唯一约束.

postgresql

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

PostgreSQL无法在PL/pgSQL中开始/结束事务

我正在寻求澄清如何在plpgsql函数中确保原子事务,以及为数据库的这个特定更改设置隔离级别.

在下面显示的plpgsql函数中,我想确保删除和插入成功.当我尝试将它们包装在一个事务中时,我收到一个错误:
ERROR: cannot begin/end transactions in PL/pgSQL.

如果另一个用户此功能删除了自定义行之后但有机会插入自定义行之前添加了环境的默认行为('RAIN','NIGHT','45MPH'),则执行下面的函数时会发生什么?行?是否存在包含插入和删除的隐式事务,以便在另一个用户更改此函数引用的任一行时回滚它们?我可以为此功能设置隔离级别吗?

create function foo(v_weather varchar(10), v_timeofday varchar(10), v_speed varchar(10),
   v_behavior varchar(10))
   returns setof CUSTOMBEHAVIOR
   as $body$
   begin

      -- run-time error if either of these lines is un-commented

      -- start transaction ISOLATION LEVEL READ COMMITTED;
      -- or, alternatively, set transaction ISOLATION LEVEL READ COMMITTED;


      delete from CUSTOMBEHAVIOR 
      where weather = 'RAIN' and timeofday = 'NIGHT' and speed= '45MPH' ;

      -- if there is no default behavior …
Run Code Online (Sandbox Code Playgroud)

transactions runtime-error plpgsql read-committed postgresql-9.2

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

SELECT或INSERT是否容易出现竞争条件?

我写了一个函数为一个简单的博客引擎创建帖子:

CREATE FUNCTION CreatePost(VARCHAR, TEXT, VARCHAR[])
RETURNS INTEGER AS $$
    DECLARE
        InsertedPostId INTEGER;
        TagName VARCHAR;
    BEGIN
        INSERT INTO Posts (Title, Body)
        VALUES ($1, $2)
        RETURNING Id INTO InsertedPostId;

        FOREACH TagName IN ARRAY $3 LOOP
            DECLARE
                InsertedTagId INTEGER;
            BEGIN
                -- I am concerned about this part.
                BEGIN
                    INSERT INTO Tags (Name)
                    VALUES (TagName)
                    RETURNING Id INTO InsertedTagId;
                EXCEPTION WHEN UNIQUE_VIOLATION THEN
                    SELECT INTO InsertedTagId Id
                    FROM Tags
                    WHERE Name = TagName
                    FETCH FIRST ROW ONLY;
                END;

                INSERT INTO Taggings (PostId, TagId) …
Run Code Online (Sandbox Code Playgroud)

sql postgresql concurrency upsert plpgsql

25
推荐指数
2
解决办法
8449
查看次数

Python/psycopg2中的优雅主键错误处理

使用Python 2.7和

在[150]中:psycopg2.版本 [150]:'2.4.2(dt dec pq3 ext)'

我有一个简单的python脚本来处理事务并将数据写入数据库.偶尔会有一个违反我的主键的插入内容.这很好,我只是想让它忽略那条记录并继续它的快乐方式.我遇到的问题是psycopg2主键错误是在错误失败后中止整个事务块和所有插入.这是一个示例错误

ERROR: duplicate key value violates unique constraint "encounter_id_pkey"
DETAIL:  Key (encounter_id)=(9012235) already exists.
Run Code Online (Sandbox Code Playgroud)

这是在下一个插入.不违反.

Inserting: 0163168~9024065
ERROR: current transaction is aborted, commands ignored until end of transaction block
Run Code Online (Sandbox Code Playgroud)

每次插入都会重复第二个错误.这是一个简化的循环.我正在循环一个pandas数据框,但它可能是任何循环.

conn = psycopg2.connect("dbname='XXXX' user='XXXXX' host='XXXX' password='XXXXX'")

cur = conn.cursor()

for i, val in df2.iteritems():
    try:
        cur = conn.cursor()
        cur.execute("""insert into encounter_id_table (
        encounter_id,current_date  )
        values       
        (%(create_date)s, %(encounter_id)s ) ;""",
        'encounter_id':i.split('~')[1],  
        'create_date': datetime.date.today() })           
        cur.commit()
        cur.close() 
    except Exception , e:
        print 'ERROR:', e[0] …
Run Code Online (Sandbox Code Playgroud)

python sql postgresql psycopg2

18
推荐指数
1
解决办法
9888
查看次数

使用ON CONFLICT从INSERT返回行而无需更新

我有一种情况,我经常需要从具有唯一约束的表中获取一行,如果不存在,则创建它并返回.例如我的表可能是:

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

它包含:

id | name
 1 | bob 
 2 | alice
Run Code Online (Sandbox Code Playgroud)

然后我想:

 INSERT INTO names(name) VALUES ('bob')
 ON CONFLICT DO NOTHING RETURNING id;
Run Code Online (Sandbox Code Playgroud)

也许:

 INSERT INTO names(name) VALUES ('bob')
 ON CONFLICT (name) DO NOTHING RETURNING id
Run Code Online (Sandbox Code Playgroud)

让它返回bob的id 1.但是,RETURNING只返回插入或更新的行.所以,在上面的例子中,它不会返回任何东西.为了让它按照需要运行,我实际上需要:

INSERT INTO names(name) VALUES ('bob') 
ON CONFLICT ON CONSTRAINT names_name_key DO UPDATE
SET name = 'bob'
RETURNING id;
Run Code Online (Sandbox Code Playgroud)

这看起来有点麻烦.我想我的问题是:

  1. 不允许(我)期望行为的原因是什么?

  2. 有没有更优雅的方式来做到这一点?

sql postgresql upsert postgresql-9.5

16
推荐指数
1
解决办法
3961
查看次数

如何在INSERT ... ON CONFLICT中包含RETURNING中的排除行

我有这个表(由Django生成):

CREATE TABLE feeds_person (
  id serial PRIMARY KEY,
  created timestamp with time zone NOT NULL,
  modified timestamp with time zone NOT NULL,
  name character varying(4000) NOT NULL,
  url character varying(1000) NOT NULL,
  email character varying(254) NOT NULL,
  CONSTRAINT feeds_person_name_ad8c7469_uniq UNIQUE (name, url, email)
);
Run Code Online (Sandbox Code Playgroud)

我想批量插入大量使用数据INSERTON CONFLICT条款.

皱纹是我需要得到所有行的id背面,无论它们是否已经存在.

在其他情况下,我会做类似的事情:

INSERT INTO feeds_person (created, modified, name, url, email)
VALUES blah blah blah
ON CONFLICT (name, url, email) DO UPDATE SET url = feeds_person.url …
Run Code Online (Sandbox Code Playgroud)

sql django postgresql upsert sql-returning

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