gpt4 book ai didi

postgresql - 如何在 PostgreSQL 9.2 中实现(或模拟)子类型多态性?

转载 作者:行者123 更新时间:2023-11-29 13:05:38 26 4
gpt4 key购买 nike

伙计们,我目前正试图回答一个大问题:“如何自己在 PostgreSQL 中实现(或至少模拟)子类型多态性”,因为我意识到 PostgreSQL 对继承的支持有些不确定。到目前为止,尽可能简单明了,这是我的方法:

CREATE TABLE TelephoneNumber (
ID serial PRIMARY KEY,
countryCode CountryCodes_e NOT NULL,
operatorPrefix OperatorPrefixes_e,
townPrefix TownPrefixes_e,
coreNumber text NOT NULL
);

CREATE TABLE CellPhoneNumber (
cellPhoneNumber_ID serial PRIMARY KEY,
countryCode CountryCodes_e,
operatorPrefix OperatorPrefixes_e,
coreNumber text NOT NULL
);

CREATE TABLE HomePhoneNumber (
homePhoneNumber_ID serial PRIMARY KEY,
countryCode CountryCodes_e,
townPrefix TownPrefixes_e,
coreNumber text NOT NULL
);

.
.
.

TABLE Operation (
...
dateAndTime timestamp,
receiverPhoneNumber int8 REFERENCES TelephoneNumber
...
);

是的,我知道这个解决方案可能看起来很糟糕,因为我将相同的信息复制到不同的表中,但这就是重点:我在整个表层次结构中实现一致性,模拟子表的属性继承(因为 PostgreSQL 赢了让我将父表 TelephoneNumber 引用到外部 Operation 表中)。我想要做的是在父表中插入一行,然后将该行传播到正确的 CellPhoneNumberHomePhoneNumber 子表中。 (请注意,在我的例子中,子表的行数(每行 1 行)少于父表)。

接下来,我写了一个触发函数:

CREATE OR REPLACE FUNCTION insertTelephoneNumberIntoProperTable_FNC() RETURNS TRIGGER AS $$
BEGIN
IF (NEW.operatorPrefix = 'N/A' AND NEW.townPrefix <> 'N/A') THEN
EXECUTE 'INSERT INTO HomePhoneNumber VALUES(' || NEW.telephoneNumber_ID || ', ' || NEW.countryCode::CountryCodes_e || ', ' || NEW.townPrefix || ', ' || NEW.coreNumber|| ');' USING NEW;
RETURN NEW;
ELSE
IF (NEW.operatorPrefix <> 'N/A' AND NEW.townPrefix = 'N/A') THEN
EXECUTE 'INSERT INTO CellPhoneNumber VALUES(' || NEW.telephoneNumber_ID || ', ' || NEW.countryCode::CountryCodes_e || ', ' || NEW.operatorPrefix || ', ' || NEW.coreNumber|| ');' USING NEW;
RETURN NEW;
END IF;
END IF;

RAISE EXCEPTION 'ERROR: Row is not valid!';
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER insertTelephoneNumberIntoProperTable_TRG
BEFORE INSERT ON TelephoneNumber
FOR EACH ROW
EXECUTE PROCEDURE insertTelephoneNumberIntoProperTable_FNC();

这将拦截 INSERTs INTO TelephoneNumber 表并确定实际存储的是哪种电话号码:如果 operatorPrefix 等于“N/A”(即存储在 'OperatorPrefixes_e' 和 'TownPrefixes_e' 枚举中的特殊值)而 townPrefix 不是,那么我确定它是一个 HomePhoneNumber 实例。这同样适用于 CellPhoneNumber 实例。

问题是,当我 INSERT INTO TelephoneNumber VALUES(DEFAULT, '39', 'N/A', '010', '7708124'); 时,我们都知道这是一个 HomePhoneNumber 实例,Postgres 提示它不能从 int 转换为枚举,指向值 '39'(意大利语国际前缀,BTW)。如果我将前缀列的类型更改为,比如说,文本 Postgres 最终将不再提示,但值仅作为触发器的结果正确存储到“父”TelephoneNumber 表中,而不是在“派生的”HomePhoneNumber 表,这表明 EXECUTE 语句根本没有效果。所以,我真正的问题是:

  1. 为什么我不能在 EXECUTE 语句中将这些值转换为枚举值? (我担心我做错了)
  2. 为什么即使将前缀列的类型更改为文本,对子表的传播也没有效果?

我在尝试将 int 值转换为枚举值时得到的确切错误是:

ERROR:  column "countrycode" is of type countrycodes_e but expression is of type integer
LINE 1: INSERT INTO HomePhoneNumber VALUES(1, 39, 010, 7708124);
^
HINT: You will need to rewrite or cast the expression.
QUERY: INSERT INTO HomePhoneNumber VALUES(1, 39, 010, 7708124);
CONTEXT: PL/pgSQL function inserttelephonenumberintopropertable_fnc() line 4 at EXECUTE statement

如您所见,我尝试在 EXECUTE 语句中强制转换枚举值,但没有成功。希望你能帮助我,因为它是 35 小时。我醒着与 pgAdmin III 战斗... D:

PS:我知道我必须编写更多函数和触发器才能保证整个层次结构的引用完整性;上面的只是一个示例,以便了解采用哪条路线。提前谢谢大家!

最佳答案

why cannot I convert those values into enum values in the EXECUTE statement?

枚举值始终是字 rune 字(需要用单引号引起来)。

所以你需要做这样的事情:

EXECUTE 'INSERT INTO HomePhoneNumber VALUES(' 
|| NEW.telephoneNumber_ID
|| ', ''' || NEW.countryCode || ''', '
|| NEW.townPrefix || ', ' || NEW.coreNumber|| ');' USING NEW;

注意表达式中添加的单引号,使“国家代码”成为字 rune 字。

关于postgresql - 如何在 PostgreSQL 9.2 中实现(或模拟)子类型多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13564416/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com