Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在PostgreSQL 9.2中实现(或模拟)子类型多态性?_Postgresql_Inheritance_Casting_Enums_Int - Fatal编程技术网

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

如何在PostgreSQL 9.2中实现(或模拟)子类型多态性?,postgresql,inheritance,casting,enums,int,Postgresql,Inheritance,Casting,Enums,Int,伙计们,我现在正试图回答一个大问题:“如何在PostgreSQL中自己实现(或至少模拟)子类型多态性”,因为我意识到PostgreSQL对继承的支持有些未定义。到目前为止,尽可能简单明了地说,这是我的方法: CREATE TABLE TelephoneNumber ( ID serial PRIMARY KEY, countryCode CountryCodes_e NOT NULL, operatorPrefix OperatorPrefixes_e, townPref

伙计们,我现在正试图回答一个大问题:“如何在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不允许我将父表电话号码引用到外部操作表中)。我要做的是在父表中插入一行,然后将该行传播到右CellPhoneNumber或HomePhoneNumber子表中。(请注意,在我的情况下,子表的行数(每个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();
如您所见,我试图在EXECUTE语句中强制转换enum值,但没有成功。希望您能帮助我,因为现在已经35小时了。我正在清醒地与pgAdmin III…D战斗:

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

为什么我不能在EXECUTE语句中将这些值转换为enum值

枚举值始终是字符文字(需要用单引号括起来)

所以你需要这样做:

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

请注意,在表达式中添加了单引号以构成“国家代码”一个字符文字。

我认为您在示例
create table
语句中缺少了
inherits
子句。而且我不会将国家前缀存储为枚举,它们应该根据inherits子句放入自己的表中,IMVHO对我的情况没有多大帮助,不是吗?我的意思是,这样做的唯一显著效果是at将子行存储到父表中,这正是我试图在函数中模拟的行为。我之所以使用函数而不是INHERITS子句,是因为这样我可以通过属性的不同来构建子表,这在我的例子中是一个优势。关于枚举,是的,这可能是一个解决方案,但是我仍然无法解释为什么将相关属性存储为简单文本而不是枚举值会阻止传播正常工作,正如我在问题2中所问的那样。:/table inheritation会将差异放入子表和父表中的公共属性中。虽然在您的情况下,只有公共属性e将是国家代码-可能不值得。当我说“差”时,我的意思是“集减法”。:)太好了!这个问题已解决#1,现在电话号码表已填充,但HomePhoneNumber和CellPhoneNumber未填充,因此问题#2仍然开放。我认为这是因为不可能通过触发器修改任何不是“引用表”的表:这就是为什么我没有在函数中仅将INSERT写为“INSERT-INTO..”,我认为EXECUTE可以作为一种变通方法,但我错了。
EXECUTE 'INSERT INTO HomePhoneNumber VALUES(' 
         || NEW.telephoneNumber_ID 
         || ', ''' || NEW.countryCode || ''', ' 
         || NEW.townPrefix || ', ' || NEW.coreNumber|| ');' USING NEW;