一个列的两个名称

Sab*_*lfy 4 postgresql database-design

我有foo一个表中命名的列。我在脚本中构建了查询,使用这个名称。

我现在想将表中的列重命名为bar. 这将破坏脚本(有几个,但如有必要,可以更改它们)。该表被其他表引用。我想重命名,因为该列中存储的内容的上下文已更改。

一个列可以有两个名称吗?

Nei*_*gan 7

我将假设您的表已命名baz并在架构中public

create table baz (
  foo text primary key
);

insert into baz (foo) values ('hello');

select foo from baz;
Run Code Online (Sandbox Code Playgroud)

现在您要重命名该列:

alter table baz rename column foo to bar;
Run Code Online (Sandbox Code Playgroud)

但是现在您的脚本已损坏:

select foo from baz; -- nope!
Run Code Online (Sandbox Code Playgroud)

因此,创建一个新模式,在其中放置一个视图,然后更改您search_path以隐藏视图“后面”的表。

create schema qux;

create or replace view qux.baz as 
    select
      bar as foo
    from public.baz;

set search_path to qux, public;

select foo from baz; -- works!
Run Code Online (Sandbox Code Playgroud)

这是一种 postgres 的方式 create synonym


Erw*_*ter 5

根据您在脚本中具体执行的操作,有多种方法可以解决该问题。我将SELECT仅出于此答案的目的而假设。但是INSERT, UPDATE,DELETE也是可能的...

VIEW

AVIEW将是一个选项,就像@Andriy 评论的那样。如果您需要将当前表保持原样,事情会变得更加复杂,但仍有可能。您可以在 schema 中表的 schema 之前列出的另一个 schema 中使用同名的aVIEW屏蔽该表search_path。实际上,我曾多次这样做以保留更新数据库模式后无法适应的接口。

基本示例代码:

CREATE SCHEMA override;

CREATE VIEW override.tbl AS
SELECT *, foo AS bar       -- to add the column a second time
    -- tbl_id, foo AS bar  -- to replace the column
FROM tbl;
Run Code Online (Sandbox Code Playgroud)

仅授予USAGE架构上的权限public以避免滥用:

GRANT USAGE ON SCHEMA override TO public;
Run Code Online (Sandbox Code Playgroud)

override作为第一个模式放入您search_path的原始查询中,“神奇地”包含另一列。如果您不想弄乱人们的search_path,您可以在每个会话开始时在脚本中动态执行此操作:

DO
$$BEGIN
EXECUTE (SELECT 'SET search_path = override,' || setting
         FROM pg_catalog.pg_settings WHERE name = 'search_path');
END$$;
Run Code Online (Sandbox Code Playgroud)

这对于 SQL 注入是安全的,因为子查询返回一个有效的搜索路径。

屏蔽函数的类似用例:

TEMPORARY VIEW

或者您可以创建一个临时视图来屏蔽表:

CREATE TEMP VIEW tbl AS
SELECT *, foo AS bar FROM tbl;
Run Code Online (Sandbox Code Playgroud)

临时对象仅在同一个会话中可见并随之消亡。

您可能需要为INSERT, UPDATE,做更多的事情DELETE。大多数实用程序命令 (DML) 不能像那样被愚弄。

“生成的列”

Postgres没有生成列本身,但可以使用的功能,看起来和作品就像一个:

CREATE TABLE tbl (tbl_id int, foo text);
INSERT INTO tbl VALUES (1, 'hello');

CREATE FUNCTION bar(tbl) RETURNS text LANGUAGE sql STABLE AS 'SELECT $1.foo';

SELECT *, t.bar
FROM   tbl t;
Run Code Online (Sandbox Code Playgroud)

详细解释:

SQL小提琴。