我想设置一个 CHECK 约束来确保text[]
列的元素仅包含某些值。
设置一个例子:
CREATE TABLE foo(
countries text[]
);
INSERT INTO foo VALUES ('{"Morocco", "Mali", "Indonesia"}');
INSERT INTO foo VALUES ('{"Sokovia", "Mali"}');
Run Code Online (Sandbox Code Playgroud)
现在只允许“摩洛哥”、“马里”和“印度尼西亚”,因此第二行应该被约束拒绝。
我有一个“有效”的解决方案:
CHECK (array_length(
array_remove(
array_remove(
array_remove(
countries,
'Indonesia'
), 'Mali'
), 'Morocco'
), 1) IS NULL)
Run Code Online (Sandbox Code Playgroud)
但这不太可读。
我也尝试过这个:
CHECK ((
SELECT unnest(countries)
EXCEPT
SELECT unnest(array['Morocco', 'Mali', 'Indonesia'])
) IS NULL)
Run Code Online (Sandbox Code Playgroud)
但:
错误无法在检查约束中使用子查询
对于 JOIN 中的每个右侧行,我想创建一个序列号,每个左侧行从 1(或 0)开始。
例子:
create table persons (person_id int, person_name text);
create table places (place_id int, person_id int, place_name text);
insert into persons values (10, 'Aulus Agerius'), (20, 'Numerius Negidius');
insert into places values (10, 10, 'Anytown'), (20, 10, 'Timbuktu'), (30, 20, 'Podunk');
Run Code Online (Sandbox Code Playgroud)
select person_name, place_name
from persons join places using (person_id)
order by person_id, place_id;
Run Code Online (Sandbox Code Playgroud)
期望的结果:
人名 | 地名 | 地点顺序 |
---|---|---|
奥鲁斯·阿杰里乌斯 | 任意镇 | 1 |
奥鲁斯·阿杰里乌斯 | 廷巴克图 | 2 |
内吉迪乌斯 | 波敦克 | 1 |
例如,2 inplace_seq
表示“这是为该人找到的第二个地方”。
如何创建place_seq
专栏?
我是这样查询的:
SELECT count(*)
FROM orders
WHERE planned_shipping_date >= '2022-04-04'
AND planned_shipping_date < '2022-04-05'
Run Code Online (Sandbox Code Playgroud)
然后我遇到了这个答案,因为在更复杂的查询中它使查询更容易阅读,所以我重写了查询,如下所示:
SELECT count(*)
FROM orders
WHERE planned_shipping_date <@ daterange('2022-04-04', '2022-04-05')
Run Code Online (Sandbox Code Playgroud)
我相信它们在语义上是相同的,但看看计划:
Aggregate (cost=76.91..76.92 rows=1 width=8) (actual time=1.066..1.068 rows=1 loops=1)
-> Index Only Scan using orders_planned_shipping_date_idx on orders (cost=0.29..69.73 rows=2872 width=0) (actual time=0.067..0.646 rows=2813 loops=1)
Index Cond: ((planned_shipping_date >= '2022-04-04'::date) AND (planned_shipping_date < '2022-04-05'::date))
Heap Fetches: 0
Run Code Online (Sandbox Code Playgroud)
Aggregate (cost=2753.57..2753.58 rows=1 width=8) (actual time=18.309..18.311 rows=1 loops=1)
-> Index Only Scan using orders_planned_shipping_date_idx on orders (cost=0.29..2751.93 rows=655 width=0) …
Run Code Online (Sandbox Code Playgroud) 这是来自 Postgres 9.6 的 EXPLAIN ANALYZE 的一部分:
-> Bitmap Heap Scan on cities (cost=90.05..806.49 rows=265 width=4) (actual time=4.733..45.772 rows=17 loops=1)
Recheck Cond: (regexp_replace(regexp_replace(replace(replace(replace(replace(lower(name), 'ä'::text, 'ae'::text), 'ö'::text, 'oe'::text), 'ü'::text, 'ue'::text), 'ß'::text, 'ss'::text), 'strasse\M'::text, 'strasse'::text, 'g'::text), '\W'::text, ''::text, 'g'::text) % 'coerde'::text)
Rows Removed by Index Recheck: 567
Heap Blocks: exact=497
-> Bitmap Index Scan on city_lookup_index (cost=0.00..89.98 rows=265 width=0) (actual time=4.229..4.229 rows=584 loops=1)
Index Cond: (regexp_replace(regexp_replace(replace(replace(replace(replace(lower(name), 'ä'::text, 'ae'::text), 'ö'::text, 'oe'::text), 'ü'::text, 'ue'::text), 'ß'::text, 'ss'::text), 'strasse\M'::text, 'strasse'::text, 'g'::text), '\W'::text, ''::text, 'g'::text) % 'coerde'::text) …
Run Code Online (Sandbox Code Playgroud) name
例如,如果我有一个带有排序规则的文本列tr-TR
,并且我运行一个查询
SELECT * FROM t WHERE name LIKE 'a%'
Run Code Online (Sandbox Code Playgroud)
然后这将进行 seq 扫描。
如果我现在创建一个索引
CREATE INDEX ON t(name text_pattern_ops)
Run Code Online (Sandbox Code Playgroud)
上面的查询将变成位图扫描。但还有另一种技术可以达到相同的结果:
CREATE INDEX ON t(name COLLATE "C")
Run Code Online (Sandbox Code Playgroud)
这些方法完全等同还是存在差异?
这里有一些可以使用的数据:
CREATE TABLE a (
a_id int NOT NULL,
a_prop text NOT NULL
);
CREATE TABLE b (
b_id int NOT NULL,
b_prop text NOT NULL
);
INSERT INTO a VALUES (1, 'blah'), (2, 'blah'), (4, 'not this one');
INSERT INTO b VALUES (1, 'blah'), (3, 'blah'), (5, 'not this one');
Run Code Online (Sandbox Code Playgroud)
现在我想编写一个返回的查询:
一种可能性是:
SELECT *
FROM a
FULL OUTER JOIN b ON a_id = b_id
WHERE (a_prop = 'blah' OR a_prop IS NULL)
AND (b_prop = 'blah' OR b_prop IS …
Run Code Online (Sandbox Code Playgroud)