小编Yog*_*sch的帖子

带索引的 JSONB 与 hstore

我试图决定数据库设计,在这个阶段尽可能少的假设(关于 web 应用程序的实际发展)。

作为第一步,了解 JOINS 是昂贵的,我正在考虑少量的整体表,而不是大量的规范化较小的表。第二点,我在使用 hstore 与常规表与 JSONB(使用 GiST 索引)之间感到困惑。

AFAIK(请随时纠正):

  1. 通常,在 Postgres 中,已知 hstore 的性能优于其他数据类型。来自 FOSDEM PGDAY 的这个演讲有一些有趣的统计数据(在幻灯片的后半部分)。 https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. hstore 的一个优势是快速索引(GiN 或 GiST)。但是,使用 JSONB,GiN 和 GiST 索引也可以应用于 JSON 数据。

  3. 来自第二象限的专业人士的这篇博客说“此时可能值得在所有新应用程序中用 jsonb 替换 hstore 使用”(滚动到最后):http ://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary -jsonhstore-dynamic-columns/

所以我想决定以下几点:

  1. 对于数据的主要(结构化)部分:它应该放在几个关系表中(相对较大,有很多列),还是应该是使用 hstore 的多个键值存储?
  2. 对于临时(用户贡献/非结构化)数据,它应该是 JSON 还是 hstore 中的临时键值存储(键存储在主要关系表之一中)?

postgresql database-design

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

在参数化查询中传递数据类型区间的值

上下文正在从其余服务器连接到 Postgres 数据库。

考虑一个假设的代表性示例:我希望能够获取帐户创建日期比任意值早/新的名称列表。

在下面的示例查询中,表结构很简单 -name是 type text,并且creation_date是 type timestamp。所以当我做类似的事情时

server_pg_module:query("select name from new_table where 
current_timestamp - creation_date < '6 days'") 
Run Code Online (Sandbox Code Playgroud)

它工作得很好。但我真正想做的是6 days从服务器获取该值。所以我尝试像

server_pg_module:query("select name from new_table where
current_timestamp - timestamp < $1", ["6 days"]
Run Code Online (Sandbox Code Playgroud)

它抛出一个错误。我试过'6 days'"'6 days'"以及其他一些混合物,都抛出错误。所以为了检查我添加了一个新interval的类型列interval并尝试了一个查询

server_pg_module:query("insert into new_table (name, interval) values ($1, '3 day')", ["fooo"]). 
Run Code Online (Sandbox Code Playgroud)

哪个有效,但是

server_pg_module:query("insert into new_table (name, interval) values ($1, $2)", ["fooo", "3 days"]). 
Run Code Online (Sandbox Code Playgroud)

休息。为了更好的衡量,除了"'3 days'"上面提到的混合物之外,我还尝试过 …

postgresql datatypes parameter interval postgresql-10

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

带有嵌套 CTE 的条件插入?

我想弄清楚是否有一种方法可以使嵌套 CTE 适用于这种特殊情况。

考虑以下基于实际应用程序的(高度人为设计的)场景:有一个员工 ID 的单列表。然后是包含所有详细信息的员工属性表。(单列表背后的主要原因通常是理所当然地需要在知道实际员工的任何详细信息之前批量创建和分配新员工 ID。)

现在到手头的任务,我们要为新员工插入详细信息(即姓名),但首先我们需要检查是否已经存在具有该姓名的员工。如果是,我们将简单地返回 id,如果不是,我们将创建一个新的员工记录,然后插入详细信息,最后返回新创建的 id。

要重新创建此测试场景:

CREATE TABLE public.employee (
    id text DEFAULT gen_random_uuid(),
    PRIMARY KEY (id)
);

CREATE TABLE public.employee_details (
    employee_id text,
    name text,
    PRIMARY KEY (employee_id),
    FOREIGN KEY (employee_id) REFERENCES public.employee(id)
);
Run Code Online (Sandbox Code Playgroud)

我试图敲定的查询如下所示。

with 
e as 
    (select name, employee_id from employee_details where name = 'jack bauer'), 

i as (insert into employee_details (name, employee_id) 
    select 'jack bauer', 
        (with a as (insert into employee values(default) RETURNING id) select a.id from a)
    where not exists …
Run Code Online (Sandbox Code Playgroud)

postgresql insert cte postgresql-10

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

一组 with 后的多个插入查询

我正在尝试以一种可重现的方式用一些测试数据填充数据库。

假设(一个过于简化的示例)三个基表:name、city、job 和两个关系表:name-city 和 name-job。我需要在三个基表中的每一个中创建一个条目,并使用上述条目在两个关系表中创建条目。

我已经拥有了一种使用一系列with查询在 3 个基表中创建条目并将值插入到一个关系表中的方法。

with x as 
(INSERT INTO "public"."name" VALUES(DEFAULT) RETURNING "id"),
y as 
(INSERT INTO "public"."job" VALUES(DEFAULT) RETURNING "id"),
z as 
(INSERT INTO "public"."city" VALUES(DEFAULT) RETURNING "id")

INSERT INTO "public"."name-job"("name", "job")  
select x.id, y.id from x,y;
Run Code Online (Sandbox Code Playgroud)

我真的想添加第二个插入语句

INSERT INTO "public"."name-city"("name", "city")  
select x.id, z.id from x,z;
Run Code Online (Sandbox Code Playgroud)

第一次插入后,但不知道如何。我曾尝试用逗号分隔两个插入语句,并将它们括在括号中,然后用逗号分隔它们,以及其他一些方法,但没有任何效果。

使用带有第二个插入的全新语句并不完全是一种选择,因为我需要使用相同的 x、y、z 值。鉴于我缺乏专业知识/经验,我完全有可能遗漏了一些明显的东西......所以任何关于我如何做到这一点的想法,理想情况下,没有高度复杂的工具,将是最受欢迎的。

FWIW,我正在使用 Postgres (10.x)

postgresql insert subquery postgresql-10

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

无法在 CTE 中使用 INSERT

我正在尝试使用 CTE 将一些随机数据插入表中 -

create table foo (id integer)

with x as (select random())
  insert into foo (id)
  select x from x
Run Code Online (Sandbox Code Playgroud)

这给出了一个错误: ERROR: column "id" is of type integer but expression is of type record

只是 CTE 的select作品:

with x as (select random())
--   insert into foo (id)
  select x from x
Run Code Online (Sandbox Code Playgroud)

我也无法打字:

with x as (select random())
  insert into foo (id)
  select x::integer from x
Run Code Online (Sandbox Code Playgroud)

这给出了一个错误:ERROR: cannot cast type record to integer

出了什么问题以及如何解决?

postgresql cte

0
推荐指数
1
解决办法
45
查看次数