Jar*_*red 10 sql postgresql node.js sql-insert
我正在node.js中编写一个函数来查询PostgreSQL表.
如果该行存在,我想从该行返回id列.
如果它不存在,我想插入它并返回id(insert into ... returning id).
我一直在尝试变体case和if else语句,似乎无法让它发挥作用.
Erw*_*ter 10
单个SQL语句中的解决方案.但需要PostgreSQL 8.4或更高版本.
请考虑以下演示:
测试设置:
CREATE TEMP TABLE tbl (
id serial PRIMARY KEY
,txt text UNIQUE -- obviously there is unique column (or set of columns)
);
INSERT INTO tbl(txt) VALUES ('one'), ('two');
Run Code Online (Sandbox Code Playgroud)
INSERT/SELECT命令:
WITH v AS (SELECT 'three'::text AS txt)
,s AS (SELECT id FROM tbl JOIN v USING (txt))
,i AS (
INSERT INTO tbl (txt)
SELECT txt
FROM v
WHERE NOT EXISTS (SELECT * FROM s)
RETURNING id
)
SELECT id, 'i'::text AS src FROM i
UNION ALL
SELECT id, 's' FROM s;
Run Code Online (Sandbox Code Playgroud)
第一个CTE v并非绝对必要,但要实现您只需输入一次值.
第二CTE S选用的id从tbl如果"行"的存在.
第三个 CTE我将 "行"插入tblif(并且仅当它)不存在时返回id.
决赛SELECT归来了id.我添加了一个src指示"源" 的列- "行"是否预先存在并id来自SELECT,或者"行"是新的,因此是id.
此版本应尽可能快,因为它不需要额外的SELECT,tbl而是使用CTE.
为了在多用户环境中保护其免受可能的竞争条件的影响:
对于在Postgres 9.5或更高版本中使用新UPSERT的更新技术:
我建议在数据库端进行检查,然后将id返回给nodejs.
例:
CREATE OR REPLACE FUNCTION foo(p_param1 tableFoo.attr1%TYPE, p_param2 tableFoo.attr1%TYPE) RETURNS tableFoo.id%TYPE AS $$
DECLARE
v_id tableFoo.pk%TYPE;
BEGIN
SELECT id
INTO v_id
FROM tableFoo
WHERE attr1 = p_param1
AND attr2 = p_param2;
IF v_id IS NULL THEN
INSERT INTO tableFoo(id, attr1, attr2) VALUES (DEFAULT, p_param1, p_param2)
RETURNING id INTO v_id;
END IF;
RETURN v_id:
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
而不是在Node.js端(我在这个例子中使用node-postgres):
var pg = require('pg');
pg.connect('someConnectionString', function(connErr, client){
//do some errorchecking here
client.query('SELECT id FROM foo($1, $2);', ['foo', 'bar'], function(queryErr, result){
//errorchecking
var id = result.rows[0].id;
};
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7283 次 |
| 最近记录: |