我正在更新Postgres 8.4数据库(来自C#代码),基本任务很简单:要么更新现有行,要么插入一个新行(如果还不存在).通常我会这样做:
UPDATE my_table
SET value1 = :newvalue1, ..., updated_time = now(), updated_username = 'evgeny'
WHERE criteria1 = :criteria1 AND criteria2 = :criteria2
Run Code Online (Sandbox Code Playgroud)
如果0行受到影响,那么执行INSERT:
INSERT INTO my_table(criteria1, criteria2, value1, ...)
VALUES (:criteria1, :criteria2, :newvalue1, ...)
Run Code Online (Sandbox Code Playgroud)
但是有一点点扭曲.我不想更改updated_time和updated_username列,除非任何新值实际上与现有值不同,以避免误导用户更新数据的时间.
如果我只是在进行UPDATE,那么我也可以为这些值添加WHERE条件,但这在这里不起作用,因为如果DB已经是最新的UPDATE将影响0行,那么我会尝试INSERT.
任何人都可以想到一个优雅的方法来做到这一点,除了SELECT,然后更新或插入?
我用CTE写了一个'upsert'查询,看起来像这样:
WITH
new_data (id, value) AS (
VALUES (1, 2), (3, 4), ...
),
updated AS (
UPDATE table t set
value = t.value + new_data.value
FROM new_data
WHERE t.id = new_data.id
RETURNING t.*
)
INSERT INTO table (id, value)
SELECT id, value
FROM new_data
WHERE NOT EXISTS (
SELECT 1 FROM updated WHERE updated.id = new_data.id
)
Run Code Online (Sandbox Code Playgroud)
但是,我需要在我的应用程序中使用新值,但此查询不会返回任何内容.添加returning *到插入的末尾将返回已插入的所有行,但不会返回任何已更新的行.
那么,问题是(如何)我可以扩展它以返回已更新的行和插入的行?
编辑:当然我可以SELECT在一个事务中运行它然后运行,但我很想知道是否有单查询方式.
sql postgresql upsert common-table-expression postgresql-9.1
我发现使用可写CTE模拟PostgreSQL中的upsert是一个非常优雅的解决方案,直到我们在Postgres中获得实际的upsert/merge.(见:https://stackoverflow.com/a/8702291/558819)
但是,有一个问题:如何插入默认值?NULL当然,使用将无助于NULL显式插入NULL,与MySQL不同.一个例子:
WITH new_values (id, playlist, item, group_name, duration, sort, legacy) AS (
VALUES (651, 21, 30012, 'a', 30, 1, FALSE)
, (NULL::int, 21, 1, 'b', 34, 2, NULL::boolean)
, (668, 21, 30012, 'c', 30, 3, FALSE)
, (7428, 21, 23068, 'd', 0, 4, FALSE)
), upsert AS (
UPDATE playlist_items m
SET (playlist, item, group_name, duration, sort, legacy)
= (nv.playlist, nv.item, nv.group_name, nv.duration, nv.sort, nv.legacy)
FROM new_values nv
WHERE …Run Code Online (Sandbox Code Playgroud) 我需要检查是否存在行.如果它不存在,则应插入.
这是在postgres,我试图通过shell脚本插入行.当我运行脚本时,它不显示错误,但即使没有匹配的行,它也不会插入到表中.
所以我来自MySQL,我可以在DUPLICATE UPDATE进行INSERT:
INSERT INTO table (a,b,c)
VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
Run Code Online (Sandbox Code Playgroud)
但是现在我正在使用PostgreSQL,并且努力添加UPSERT功能,看起来MERGE可能适用于我想要的但想看看这是否是最优化的语法.示例语法1,我也看过这个,但不明白如何实现.我还没有尝试过这个,因为我认为MERGE用于合并从table1到Table2的数据或者这样的工作?
MERGE
INTO table
USING table
ON c = 1
WHEN MATCHED THEN
UPDATE
SET c=c+1
WHEN NOT MATCHED THEN
INSERT (a,b,c)
VALUES (1,2,3)
Run Code Online (Sandbox Code Playgroud)
还有其他建议吗?
MongoDB上限集合的基础是它们允许您设置表的最大大小,并且系统将在达到大小限制时清除旧数据.
有没有人想出PostgreSQL中的类似设置并在生产中使用它?
我为我创建了以下函数postgresql:
CREATE FUNCTION myfunc(param INT) RETURNS VOID AS..
Run Code Online (Sandbox Code Playgroud)
如果没有 ,我该如何调用该函数SELECT?当我运行时SELECT myfunc(1)它会工作,即使它不会按设计返回任何内容。
但我想在没有 select, just 的情况下运行它myfunc(1),这不起作用并告诉我Syntax error at 1。
我正在尝试在 PostgreSQL 中的重复更新中实现插入中的 db_merge 函数?。
我无法SELECT db_merge(..)从 java 运行,因为这会给我一个"A result was returned when none was expected."), PSQLState.TOO_MANY_RESULTS)错误。
在我的一个工作脚本中,基于某些指标存储聚合计数,我没有使用Eloquent,因为查询有点复杂,并且使用查询构建器很容易编写.我目前从数据库中获取值,我需要在数据库中插入/更新它.使用Query Builder可以实现upsert操作是否可以使用Query Builder实现?或者我是否每次都需要检查此条目是否在数据库中?
我总共有100,000个条目,并希望将其作为日常工作运行.因此,如果我需要检查数据库中是否存在特定条目,我需要多次访问数据库.有替代解决方案吗?
我正在考虑创建两个模型类,一个使用Eloquent,另一个使用查询构建器.我可以在Eloquent模型中使用我的自定义查询吗?
query-builder laravel eloquent laravel-5 laravel-query-builder
我有两个具有相同列的表,第一列是名称,第二列是计数.我想合并这些表,以便每个名称都显示两个表的添加计数:
Table1: Table2: Result Table:
NAME COUNT NAME COUNT NAME COUNT
name1 1 name3 3 name1 1
name2 2 name4 4 name2 2
name3 3 name5 5 name3 6
name4 4 name6 6 name4 8
name5 5
name6 6
Run Code Online (Sandbox Code Playgroud)
到目前为止,我已经创建了一个非常难看的结构来执行此操作,并且想知道是否有可能以更优雅的方式获得结果.
到目前为止我所拥有的(表1是test1,表2是test2):
create table test1 ( name varchar(40), count integer);
create table test2 ( name varchar(40), count integer);
create table test3 ( name varchar(40), count integer);
create table test4 ( name varchar(40), count integer);
create table test5 ( name varchar(40), count …Run Code Online (Sandbox Code Playgroud) 我目前正在使用pg_dump备份整个数据库:
<?php
include_once("../db.php");
$password = getPGPassword();
$user = getPGUser();
$db = getPGDb();
putenv("PGPASSWORD=" . $password);
$dumpcmd = array("pg_dump", "-i", "-U", escapeshellarg($user), "-F", "c", "-b", "-v", "-f", escapeshellarg('/var/www/backups/backup-'.time().'.sql'), escapeshellarg($db));
exec( join(' ', $dumpcmd), $cmdout, $cmdresult );
putenv("PGPASSWORD");
?>
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用psql来恢复整个数据库,但有没有办法可以使用查询有选择地恢复表的一部分?我能想到的最简单的事情是使用psql创建一个临时数据库,从所需的表中读取行,根据主串行键删除冲突的行,然后插入表中.
有一个更好的方法吗?我需要完整的SQL查询功能.