2009-08-24 10 views
10

जब मैं एक पुनर्लेखन नियम का उपयोग करता हूं जो एक तालिका में दो तालिकाओं में सम्मिलित करने के लिए एक तालिका में एक प्रविष्टि को विभाजित करता है जहां सम्मिलित मानों में से एक डिफ़ॉल्ट रूप से डिफ़ॉल्ट होता है ('some_sequence ') दोनों तालिकाओं के लिए समान अनुक्रम के साथ, फिर दो तालिकाओं में सम्मिलित डिफ़ॉल्ट मान भिन्न होते हैं। यह शायद पुनर्लेखन नियम द्वारा सरल पाठ प्रतिस्थापन के कारण है। मैंने अपेक्षा की थी कि डिफ़ॉल्ट मान पहले हल किया जाएगा और फिर एक ही मान दोनों टेबलों पर लिखा जाएगा।पोस्टग्रेएसक्यूएल के नियम और अगली कड़ी()/सीरियल समस्या (बहुत पोस्टग्रेएसक्यूएल-विशिष्ट)

यहाँ

एक उदाहरण (जैसा कि आप शायद लगता है, मैं विशेषज्ञता/सामान्यीकरण नियमों का उपयोग कर लागू करने के लिए कोशिश कर रहा हूँ):

-- first and third commands can be skipped if id is defined as serial 
create sequence parents_id_seq; 
create table Parents(
    id integer default(nextval('parents_id_seq')) primary key, 
    type varchar(50) not null check(type in ('Child1', 'Child2')), 
    unique (id, type), 
    attribute1 varchar(50) not null unique check(length(attribute1) > 0) 
); 
alter sequence parents_id_seq owned by parents.id; 

डेटा पहली तरह के बच्चों के लिए विशेष

create table Partial_Children1(
    id integer default(nextval('parents_id_seq')) primary key, 
    type varchar(50) not null check(type = 'Child1'), 
    foreign key (id, type) references Parents(id, type), 
    attribute2 varchar(50) not null check(length(attribute2) > 0) 
); 
में रखा जाता है

अगला मैंने उपरोक्त दोनों टेबलों में शामिल होने वाले बच्चे 1 को परिभाषित किया है (मैं स्पष्ट रूप से यह बताकर दृश्य को फिर से लिखता हूं कि पोस्टग्रेएसक्यूएल दस्तावेज के अनुसार विचारों को परिभाषित करने के लिए क्या करता है)

create table Children1(
    id int default(nextval('parents_id_seq')), 
    type varchar(50) not null check(type in ('Child1')), 
    attribute1 varchar(50) not null check(length(attribute1) > 0), 
    attribute2 varchar(50) not null check(length(attribute2) > 0) 
); 
create rule "_RETURN" as on select to Children1 do instead 
    select p.*, c.attribute2 
    from Parents p 
    join Partial_Children1 c 
     on p.id = c.id; 

अंत में पुनर्लेखन नियम मैं हो रही है के साथ समस्याओं:

create rule ct_i_children1 as 
    on insert to Children1 
    do instead (
    insert into Parents(attribute1, type) 
     values(new.attribute1, 'Child1'); 
    insert into Partial_Children1(attribute2, type) 
     values(new.attribute2, 'Child1'); 
); 

insert into Children1 (attribute1, attribute2) 
    values ('a1', 'a2'), 
     ('b1', 'b2'); 

साथ डेटा सम्मिलित करने के लिए कोशिश कर रहा त्रुटि संदेश

ERROR: insert or update on table "partial_children1" violates foreign key constraint "partial_children1_id_fkey" 
DETAIL: Key (id,type)=(3,Child1) is not present in table "parents". 

पैदावार इस हल करने के लिए एक तरह से

द्वारा पुनर्लेखन नियम के दूसरे सम्मिलन को प्रतिस्थापित कर रहा है
insert into Partial_Children1(id, attribute2, type) 
    select p.id, new.attribute2, p.type 
    from Parents p 
    where p.attribute1 = new.attribute1 

लेकिन यह विशेषता 1 की विशिष्टता पर निर्भर करता है, जिसे मैं लागू नहीं करना चाहता हूं। एक और समाधान मानों को पहले अस्थायी तालिका में सम्मिलित करना होगा, और उसके बाद दो तालिकाओं में सम्मिलन के लिए दो बार चयन करना होगा। लेकिन मुझे प्रदर्शन कारणों से यह पसंद नहीं है।

क्या किसी के पास एक और विचार है कि दोनों तालिकाओं में समान डिफ़ॉल्ट मान कैसे प्राप्त करें (केवल नियमों का उपयोग करके और ट्रिगर नहीं)?

उत्तर

5

डॉक्स http://www.postgresql.org/docs/8.4/static/rules.html

यह (नियम प्रणाली) से संशोधित करता प्रश्नों को ध्यान में नियम लेने के लिए, और तो योजना और निष्पादन के लिए क्वेरी योजनाकार करने के लिए संशोधित क्वेरी गुजरता

इसलिए यह पहले कुछ भी निष्पादित किए बिना प्रश्नों को फिर से लिखता है।

आप यह काम जब आप एक बार में multipe रिकॉर्ड सम्मिलित नहीं कर सकते हैं:

create or replace rule ct_i_children1 as 
    on insert to Children1 
    do instead (
    insert into Parents(id, attribute1, type) 
     values(nextval('parents_id_seq'), new.attribute1, 'Child1'); 
    insert into Partial_Children1(id, attribute2, type) 
     values(currval('parents_id_seq'), new.attribute2, 'Child1'); 
); 

तो फिर तुम कर सकते हैं:

insert into Children1 (attribute1, attribute2) values ('a1', 'a2'); 
insert into Children1 (attribute1, attribute2) values ('b1', 'b2'); 

नहीं बल्कि

insert into Children1 (attribute1, attribute2) 
    values ('a1', 'a2'), 
     ('b1', 'b2'); 

तो तुम सच में मुश्किल currval() कॉल के साथ नियम प्रणाली का उपयोग नहीं करना चाहिए।

साथ ही इन पृष्ठों पर टिप्पणी पर एक नज़र डालें:

एक और टिप: PostgreSQL मेलिंग सूची पर समर्थन के रूप में के रूप में उत्कृष्ट है डेटाबेस इंजन ही!

और वैसे: क्या आप जानते हैं कि postgresql के पास विरासत के बाहर विरासत के लिए समर्थन है?

सारांश: आप ट्रिगर का उपयोग या अनेक पंक्ति आवेषण से बचना चाहिए!

+0

लिंक के लिए धन्यवाद। वे समस्या का समाधान नहीं करते हैं, लेकिन कम से कम मैं अब अकेला महसूस नहीं करता ;-)। बिल्ट-इन विरासत में जो कुछ भी मैं चाहता था वह काफी ऑफर नहीं करता था। –

0

नियम आपके लिए यह करेंगे - वे निष्पादित होने से पहले क्वेरी को फिर से लिखते हैं।

जब तक आपके पास आधार (बच्चों 1) के लिए वास्तविक तालिका हो, मुझे लगता है कि आप एक ही चीज़ को एक नियम के बजाय एक ट्रिगर के साथ पूरा करने में सक्षम होंगे।

+0

क्षमा करें, लेकिन क्या आपने मेरा प्रश्न पूरी तरह पढ़ा? –

+0

उम, मैंने सोचा कि मैंने किया था। लेकिन मुझे लगता है कि कम से कम "ट्रिगर्स" भाग को याद नहीं किया, इसके बारे में खेद है। –

+0

और नियम गलत परिणाम देते हैं ;-)। –

संबंधित मुद्दे