我正在使用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)
但首先,这对于我需要的东西是否过度,其次,我怎样才能将其中一个作为简单的字符串执行?
我有一个这种布局的表:
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.我想允许NULL在MenuId存储不具有关联菜单中的最爱,但我只希望每个用户/食谱对这些行中最多只有一个.
我到目前为止的想法是:
使用一些硬编码的UUID(例如全零)而不是null.
但是,MenuId每个用户的菜单都有一个FK约束,所以我必须为每个用户创建一个特殊的"空"菜单,这是一个麻烦.
使用触发器检查是否存在空条目.
我认为这是一个麻烦,我喜欢尽可能避免触发器.另外,我不相信他们能保证我的数据永远不会处于不良状态.
只需忘记它并检查中间件或插入函数中是否存在空条目,并且没有此约束.
我正在使用Postgres 9.0.
我有什么方法可以忽略吗?
我在表中两列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) 我想通过一个查询将数据插入到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
我正在使用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有一个唯一约束.
我正在寻求澄清如何在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
我写了一个函数为一个简单的博客引擎创建帖子:
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) 使用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) 我有一种情况,我经常需要从具有唯一约束的表中获取一行,如果不存在,则创建它并返回.例如我的表可能是:
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)
这看起来有点麻烦.我想我的问题是:
不允许(我)期望行为的原因是什么?
有没有更优雅的方式来做到这一点?
我有这个表(由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)
我想批量插入大量使用数据INSERT与ON 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) postgresql ×9
sql ×6
upsert ×4
plpgsql ×2
python ×2
sql-insert ×2
concurrency ×1
django ×1
null ×1
psycopg2 ×1
transactions ×1