在PostgreSQL中创建“表格表”或实现类似的功能?

时间:2011-11-17 05:36:27

标签: postgresql database-design

我刚开始使用PostgreSQL,而且我是数据库设计的新手。

我正在编写软件,其中有各种插件可以更新数据库。每个插件定期更新数据库中自己指定的表。因此,名为“KeyboardPlugin”的插件将更新“KeyboardTable”,而“MousePlugin”将更新“MouseTable”。我希望我的数据库能够存储这些“插件表”关系,同时强制执行参照完整性。理想情况下,我想要一个包含以下列的配置表:

  1. 插件名称(类型'文字')
  2. 表名(类型?)
  3. 我的软件将从此配置表中读取,以帮助插件确定要更新的表。最初,我的想法是让第二列(Table-Name)为'text'类型。但是,如果某人错误输入了表名,或者由于某人删除了某个表而导致现有关系变得无效,那么我们就会遇到问题。我希望'Table-Name'列作为对另一个表的引用,同时强制引用完整性。

    在PostgreSQL中执行此操作的最佳方法是什么?随意建议一种全新的方式来设置我的数据库,这与我目前正在探索的不同。此外,如果它可以帮助您回答我的问题,我正在使用pgAdmin工具来设置我的数据库。

    感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

我会按原计划将名称存储为文本。通过另外存储架构名称可能会增强:

 addin text
,sch   text
,tbl   text

表系统目录中有OIDpg_catalog.pg_class)。你可以得到nifty special cast

的人
SELECT 'myschema.mytable'::regclass

但是OID可以改变转储/恢复。因此,只需将名称存储为文本,并通过在应用程序时演示的方式对其进行验证来验证表格。

当然,如果你将每个表用于多个插件,那么制作一个单独的表可能会付出代价

CREATE TABLE tbl (
 ,tbl_id serial PRIMARY KEY
 ,sch    text
 ,name   text
 );

并在......中引用它。

CREATE TABLE addin (
 ,addin_id serial PRIMARY KEY
 ,addin    text
 ,tbl_id   integer REFERENCES tbl(tbl_id) ON UPDATE CASCADE ON DELETE CASCADE
 );

如果addins有多个表,甚至可以使它成为n:m关系。但请注意,正如@OMG_Ponies评论的那样,这样的设置将要求您执行大量动态SQL,因为您事先并不知道标识符。

答案 1 :(得分:1)

我猜所有插件都有一组基本属性,然后每个插件都有一组特定于插件的属性。如果是这种情况,您可以将单个表与hstore数据类型(仅需要安装的标准扩展)一起使用。

这样的事情:

 CREATE TABLE plugins 
 (
    plugin_name              text not null primary key,
    common_int_attribute     integer not null, 
    common_text_attribute    text not null, 
    plugin_atttributes       hstore
 )

然后你可以这样做:

 INSERT INTO plugins 
 (plugin_name, common_int_attribute, common_text_attribute, hstore)
 VALUES
 ('plugin_1', 42, 'foobar', 'some_key => "the fish", other_key => 24'), 
 ('plugin_2', 100, 'foobar', 'weird_key => 12345, more_info => "10.2.4"');

这会创建两个名为plugin_1和plugin_2

的插件

Plugin_1具有附加属性“some_key”和“other_key”,而plugin_2存储键“weird_key”和“more_info”。

您可以为这些hstore列编制索引,并非常有效地查询它们。
以下将选择所有已定义键“weird_key”的插件。

SELECT *
FROM plugins
WHERE plugin_attributes ? 'weird_key'


以下语句将选择具有值为some_key的键the fish的所有插件:

SELECT *
FROM plugins
WHERE plugin_attributes @> ('some_key => "the fish"')

在我看来比使用EAV模型更方便(并且最可能也更快)。

唯一的缺点是你通过这种方法失去了类型安全性(但通常你也会因为EAV概念而失去它)。

答案 2 :(得分:1)

您不需要应用程序目录。只需将应用程序名称添加到表的键中即可。这当然假设所有表都具有相同的结构。如果不是:使用应用程序名称作为表名,或者像其他人建议的那样:作为模式名称(也允许每个应用程序使用多个表)。

编辑: 但真正的问题当然是你应该首先为你的数据建模,而构建应用程序来操纵它。 数据不应该为代码服务;代码应该提供数据。