小编bel*_*daz的帖子

Postgresql 无需超级用户即可启用扩展

我有一个 PostgreSQL 9.5 服务器,上面有自动为用户创建角色和数据库的脚本。在这些数据库中启用特定扩展(例如 pgcrypto)会很有帮助,但据我所知,必须是超级用户才能运行CREATE EXTENSION. 有没有办法在不使用超级用户帐户手动登录的情况下启用此类扩展?

postgresql permissions postgresql-extensions

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

通过 PostgreSQL 中的视图和触发器跟踪当前用户

我有一个 PostgreSQL (9.4) 数据库,它根据当前用户限制对记录的访问,并跟踪用户所做的更改。这是通过视图和触发器实现的,并且在大多数情况下效果很好,但是我在需要INSTEAD OF触发器的视图上遇到了问题。我试图减少问题,但我提前道歉,这仍然很长。

情况

到数据库的所有连接都是通过单个帐户从 Web 前端建立的dbweb。连接后,角色将通过SET ROLEWeb 界面更改为对应的人,所有此类角色都属于组角色dbuser。(有关详细信息,请参阅此答案)。让我们假设用户是alice

我的大部分表都放置在一个架构中,在这里我将调用该架构private并属于dbowner. 这些表不能直接dbuser被其他角色访问,但可以被其他角色访问dbview。例如:

SET SESSION AUTHORIZATION dbowner;
CREATE TABLE private.incident
(
  incident_id serial PRIMARY KEY,
  incident_name character varying NOT NULL,
  incident_owner character varying NOT NULL
);
GRANT ALL ON TABLE private.incident TO dbview;
Run Code Online (Sandbox Code Playgroud)

特定行对当前用户的可用性alice由其他视图确定。一个简化的例子(可以减少,但需要以这种方式来支持更一般的情况)是:

-- Simplified case, but in principle could join multiple tables to determine allowed ids …
Run Code Online (Sandbox Code Playgroud)

postgresql trigger view

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

PostgreSQL bytea 与 smallint[]

我希望将大型 (100Mb -- 1 GB) 多通道时间序列数据导入 PostgreSQL 数据库。数据来自EDF 格式的文件,这些文件将数据分块成“记录”或“时期”,每个“记录”或“时期”通常为几秒钟。每个时期的记录将每个数据通道的信号保存为短整数的顺序数组。

我被要求将文件存储在数据库中,在最坏的情况下存储为 BLOB。鉴于此,我想研究可以让我对数据库中的数据做更多事情的选项,例如促进基于信号数据的查询。

我最初的计划是将数据存储为每个纪元记录一行。我想要权衡的是是否将实际信号数据存储为 bytea 或 smallint[](甚至 smallint[][])类型。有人可以推荐一个吗?我对存储和访问成本感兴趣。用法很可能是插入一次,偶尔读取,从不更新。如果一个更容易包装为自定义类型,以便我可以添加用于分析比较记录的函数,那就更好了。

毫无疑问,我缺乏细节,所以请随时对您希望我澄清的内容添加评论。

postgresql datatypes blob bytea

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

PostgreSQL 在查询 INSTEAD OF 触发器时使用 NEW

我无法让 INSTEAD OF 触发器正常工作,而且我想我误解了如何使用 NEW。考虑以下简化场景:

CREATE TABLE Product (
  product_id SERIAL PRIMARY KEY,
  product_name VARCHAR
);
CREATE TABLE Purchase (
  purchase_id SERIAL PRIMARY KEY,
  product_id INT REFERENCES Product,
  when_bought DATE
);

CREATE VIEW PurchaseView AS
SELECT purchase_id, product_name, when_bought
FROM Purchase LEFT JOIN Product USING (product_id);
Run Code Online (Sandbox Code Playgroud)

我希望能够创建INSTEAD OF触发器以允许我直接插入到 中PurchaseView,例如:

INSERT INTO Product(product_name) VALUES ('foo');
INSERT INTO PurchaseView(product_name, when_bought) VALUES ('foo', NOW());
Run Code Online (Sandbox Code Playgroud)

我的想法是这样的:

CREATE OR REPLACE FUNCTION insert_purchaseview_func()
  RETURNS trigger AS
$BODY$
BEGIN
  INSERT INTO Purchase(product_id, when_bought) …
Run Code Online (Sandbox Code Playgroud)

postgresql trigger syntax plpgsql

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

PostgreSQL区间划分

这个问题已经出现过几次了,例如在postgresql 新闻组wiki中。一般来说,不同intervals 之间的关系可能没有明确定义 - 一个月可能有不同的天数,具体取决于所考虑的月份(和年份)。但有时需要计算两个时间点之间发生了多少个间隔,例如(简化示例):

CREATE TABLE recordings(tstart timestamp, tend timestamp, interval ticklength);

SELECT (tend - tstart) / ticklength AS numticks
FROM recordings;
Run Code Online (Sandbox Code Playgroud)

这在 PostgreSQL 中是不允许的,因为它是两个间隔之间的划分,由于上述原因,这不会有明确定义的一般行为。当间隔可以转换为秒时,存在一种解决方法,但如果不是这种情况,例如当间隔为毫秒量级时,最好的方法是什么?

postgresql time

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

PostgreSQL 随机组合与 LATERAL

在下面的示例中,我有一个表foo,我想从中随机选择每组的一行。

CREATE TABLE foo (
  line INT
);
INSERT INTO foo (line)
SELECT generate_series(0, 999, 1);
Run Code Online (Sandbox Code Playgroud)

假设我想按 分组line % 10。我可以这样做:

SELECT DISTINCT ON (bin) bin, line
FROM (
    SELECT line, line % 10 AS bin, random() x
    FROM foo
    ORDER BY x
) X
Run Code Online (Sandbox Code Playgroud)

我想做的是多次从每个垃圾箱中随机选择。我原以为我能和做到这一点generate_series(),并LATERAL

SELECT i, line, bin
FROM
(
 SELECT generate_series(1,3) i
) m,
LATERAL
(SELECT DISTINCT ON (bin) bin, line
FROM (
    SELECT line, line % 10 bin, random() x …
Run Code Online (Sandbox Code Playgroud)

postgresql random subquery

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

从 plpgsql 中的文本动态转换

我的数据库中的许多表共享一个公共布局,特别是它们有一个serial以关系名称命名的主键。从 Web 应用程序中更新这些表通常涉及以下形式的查询:

UPDATE table SET attribute = x WHERE table_id = y
Run Code Online (Sandbox Code Playgroud)

这很常见,以至于我有一个执行此任务的存储过程:

CREATE OR REPLACE FUNCTION setvalue(
    relname text,
    row_id integer,
    colname text,
    newvalue text)
RETURNS void AS
$BODY$
BEGIN
  EXECUTE format('UPDATE %I SET %I = $1 WHERE %I = $2', relname, colname, relname || '_id', colname) USING row_id;
END;
$BODY$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不适用于非文本类型。例如,更新一date列给出ERROR: column ... is of type date but expression is of type text. 假设文本是预期类型的​​有效文字表示,是否有一种安全的方法让 DBMS 找出正确的类型并做正确的事情?

postgresql dynamic-sql plpgsql

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

PostgeSQL 的代理身份验证

以下似乎可能是一种相当普遍的情况,但我还没有看到任何解决方案。

我有一个 PostgreSQL 数据库,其中包含特定于 的视图,$user以便根据某些特定于数据库的 ACL 逻辑来限制数据。数据库通常通过 JDBC 访问,特别是在 Web 界面的 JSP 中。用户通过 LDAP 密码认证登录网站。

我想要的是利用从 JDBC 连接到数据库的视图。但通常这个中间层连接是使用通用用户创建的,而不是特定于登录网站的人。我相信在 Oracle 中“正确”的方法是Proxy Authentication,但 AFAIAA 没有与 PostgreSQL 等效的方法。那么该怎么做呢?

想到了一些想法:

  • 给所有用户的数据库帐户设置相同的密码,然后使用这个通用密码创建特定于用户的 JDBC 连接(这感觉太不对了……)
  • 将用户的登录密码存储在网站某处,在创建数据库连接时重复使用(再次,这个感觉很错误)

还有其他(希望更好)的建议吗?

postgresql authentication jdbc connections

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

替换 PostgreSQL 中的大对象

当人们希望用一个新的大对象替换一个大对象时应该怎么做。一个示例是使用新版本更新上传的文件。

一种方法大概是创建一个新的大对象,更新到新 oid 的链接,然后取消旧对象的链接。但是替换现有数据是否合理,例如,通过覆盖原始数据(可能首先截断内容)?

FWIW 我会在 JDBC 和 PostgreSQL 9.4 中这样做。

postgresql jdbc blob

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

通过连接插入多个值

我有三个表,代表两个实体和一个连接关系。每个实体关系都有一个人工代理键​​,用于代替自然键的外键约束。

CREATE TABLE Person (
person_id SERIAL PRIMARY KEY,
username VARCHAR NOT NULL UNIQUE
);

CREATE TABLE Group (
group_id SERIAL PRIMARY KEY,
group_name VARCHAR NOT NULL UNIQUE
);

CREATE TABLE GroupMember (
person_id INTEGER REFERENCES Person,
group_id INTEGER REFERENCES Group,
PRIMARY KEY (person_id, group_id)
);
Run Code Online (Sandbox Code Playgroud)

我想在关系中插入多个条目GroupMember,但使用关联实体的自然键。类似的东西:

INSERT INTO GroupMember (person_id,group_id)
SELECT person_id,group_id
FROM Person P, Group G, (
('alice','girls'),
('bob','boys'),
('alice','coolkids'),
('bob','coolkids')
) AS X
WHERE P.username = X.1 AND G.group_name = X.2;
Run Code Online (Sandbox Code Playgroud)

显然,上述语法无效,但希望能传达这个想法。有没有办法在 PostgreSQL 中做到这一点?

postgresql join insert

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

用于比较表示的准确 PG 数据库大小

我有一个 Java/JDBC 程序,它获取一个示例文件并将数据导入数据库,将其分解为多个关系。该程序针对几种不同的表示多次执行此操作,其中一种使用大对象。我可以分享这些表示的更多细节,但它们很长并且与这个问题无关,因为我正在寻找一些通用的东西。

我想通过在每次导入后检查数据库的大小来比较这些不同表示的大小。该数据库位于 PostgreSQL 9.4 本地 Windows 服务器实例上,没有其他用户和默认配置。它的唯一目的是进行这个测试。

我最初的计划是这样的:

for each representation {
  call VACUUM ANALYZE
  record old DB size with SELECT pg_tablespace_size('pg_default');
  import data into database
  call VACUUM ANALYZE
  record new DB size with SELECT pg_tablespace_size('pg_default');
  store storage cost as new DB size - old DB size
}
Run Code Online (Sandbox Code Playgroud)

显然这种方法有局限性,但我的期望是对于大文件(~100MB),报告的存储成本应该是合理的近似值。请注意,我使用pg_tablespace_size是为了包含主架构之外的数据的贡献,例如大对象(inpg_catalog.pg_largeobjectpg_catalog.pg_largeobject_metadata)。

我想知道这是否是一种正确的方法,以及是否有更好的方法。我不确定是否VACUUM ANALYZE正确更新了 使用的统计信息pg_tablespace_size,即使它是在同一会话中调用的。如果我可以避免调用VACUUM ANALYZE,也会更好,因为这需要以超级用户身份连接才能运行pg_catalog关系。

有什么想法吗?

postgresql performance jdbc performance-tuning

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