Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

Oracle SQL पर इस ट्रिगर को कैसे कार्यान्वित करें?

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

मैंने NULL . को अनुमति न देने के लिए आपकी तालिका में बदलाव किया है PRIMARY KEY इन उदाहरणों में।

शुरू करने के लिए, टेबल बनाएं:

CREATE TABLE CLIENTS (
  CLIENTID    VARCHAR2(15) NOT NULL,
  DNI         VARCHAR2(9),
  NAME        VARCHAR2(100) NOT NULL,
  SURNAME     VARCHAR2(100) NOT NULL,
  SEC_SURNAME VARCHAR2(100),
  EMAIL       VARCHAR2(100) NOT NULL,
  PHONEN      NUMBER(12),
  BIRTHDATE   DATE,
  CONSTRAINT PK_CLIENTS PRIMARY KEY (CLIENTID),
  CONSTRAINT UK1_CLIENTS UNIQUE (DNI),
  CONSTRAINT UK2_CLIENTS UNIQUE (EMAIL),
  CONSTRAINT UK3_CLIENTS UNIQUE (PHONEN)
);

CREATE TABLE CONTRACTS (
  CONTRACTID    VARCHAR2(10) NOT NULL,
  CLIENTID      VARCHAR2(15) NOT NULL,
  STARTDATE     DATE          NOT NULL,
  ENDDATE       DATE,
  CONTRACT_TYPE VARCHAR2(50),
  ADDRESS       VARCHAR2(100) NOT NULL,
  TOWN          VARCHAR2(100) NOT NULL,
  ZIPCODE       VARCHAR2(8)   NOT NULL,
  COUNTRY       VARCHAR2(100) NOT NULL,
  CONSTRAINT PK_CONTRACTS PRIMARY KEY (CONTRACTID),
  CONSTRAINT FK_CONTRACTS1 FOREIGN KEY (CLIENTID) REFERENCES CLIENTS
);

फिर, पहला CLIENT बनाएं रों:

INSERT INTO CLIENTS VALUES (1,NULL,'Frodo','Baggins',NULL,'[email protected]',NULL,NULL);
INSERT INTO CLIENTS VALUES (2,NULL,'Chewbacca','UNKNOWN',NULL,'[email protected]',NULL,NULL);
COMMIT;

फिर एक TRIGGER बनाएं . इस पहले उदाहरण में, TRIGGER एक AFTER STATEMENT है type.
यह सरल लेकिन अक्षम है क्योंकि यह प्रत्येक . का मूल्यांकन करता है CLIENT प्रत्येक INSERT . के बाद कथन।
एक बड़े डेटा सेट के विरुद्ध, या एकाधिक TRIGGER के सामने s, यह एक समस्या हो सकती है।
यह TRIGGER पिछले अनुबंध की जांच करेगा और उसका ENDDATE सेट करेगा नए अनुबंध से एक दिन पहले, यदि यह शून्य है या नया अनुबंध शुरू होने के बाद।

CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
  AFTER INSERT ON CONTRACTS
  BEGIN
    MERGE INTO CONTRACTS
    USING (
            SELECT CONTRACTID,
              CANDIDATE_ENDDATE AS ENDDATE
            FROM
              (SELECT CONTRACTS.CONTRACTID,
                 (TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
                 DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
               FROM CONTRACTS)
            WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
    ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
    WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
    WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
  END;
  /

फिर, इसका परीक्षण करें।
प्रारंभिक अनुबंध जोड़ें। कोई अंतिम तिथि परिवर्तन अपेक्षित नहीं है, क्योंकि ये पहले हैं। यहां फ्रोडो के अनुबंध की समाप्ति तिथि पहले से ही निर्धारित है।

INSERT INTO CONTRACTS VALUES('Break-Ring',1,TO_DATE('19560511','YYYYMMDD'), TO_DATE('19851014','YYYYMMDD'), NULL, 'No 1', 'Doom Mountain', 'MORD', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('SaveGalaxy',2,TO_DATE('19770615','YYYYMMDD'), NULL, NULL, 'No 75', 'Rwookrrorro', 'RWKR', 'Kashyyyk');

SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID  CLIENTID  STARTDATE  ENDDATE    
Break-Ring  1         11-MAY-56  14-OCT-85  
SaveGalaxy  2         15-JUN-77             

फिर नए अनुबंध जोड़ें।
फ्रोडो का नया अनुबंध उसके मौजूदा अनुबंध की समाप्ति से पहले शुरू होता है, इसलिए समाप्ति तिथि समायोजित की जाएगी।
चेवी के प्रारंभिक अनुबंध में कोई ENDDATE नहीं था, इसलिए इसे भी समायोजित किया जाएगा।

INSERT INTO CONTRACTS VALUES('GoBackHome',1,TO_DATE('19570219','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('DefendHoth',2,TO_DATE('19801115','YYYYMMDD'), NULL, NULL, 'Meteor Crater', 'Ice Ridge', 'METEO', 'Hoth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID  CLIENTID  STARTDATE  ENDDATE    
Break-Ring  1         11-MAY-56  18-FEB-57  
GoBackHome  1         19-FEB-57             
SaveGalaxy  2         15-JUN-77  14-NOV-80  
DefendHoth  2         15-NOV-80             

और जैसे-जैसे अन्य अनुबंधों पर हस्ताक्षर किए जाते हैं, पैटर्न जारी रहता है:

INSERT INTO CONTRACTS VALUES('GoWedding',2,TO_DATE('19830309','YYYYMMDD'), NULL, NULL, 'Main Hall', 'Grand Palace', 'ALLNC', 'Coruscant');
INSERT INTO CONTRACTS VALUES('Gardening',1,TO_DATE('19570503','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID  CLIENTID  STARTDATE  ENDDATE    
Break-Ring  1         11-MAY-56  18-FEB-57  
GoBackHome  1         19-FEB-57  02-MAY-57  
Gardening   1         03-MAY-57             
SaveGalaxy  2         15-JUN-77  14-NOV-80  
DefendHoth  2         15-NOV-80  08-MAR-83  
GoWedding   2         09-MAR-83             

इस क्वेरी पर कार्यभार को स्थिर करने के लिए, इसके बजाय एक कंपाउंड ट्रिगर का उपयोग किया जा सकता है। यह दूसरा उदाहरण पहले जैसा ही परिणाम प्राप्त करता है, लेकिन केवल CONTRACT . से पूछताछ करता है CLIENT . के रों जो बदल गए हैं:

सबसे पहले, ROLLBACK; फिर, TRIGGER . द्वारा उपयोग किए जाने के लिए एक प्रकार बनाएं :

CREATE OR REPLACE TYPE NUMBER_LIST IS TABLE OF NUMBER;
/

फिर COMPOUND TRIGGER बनाएं :

CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
FOR INSERT ON CONTRACTS
COMPOUND TRIGGER
  V_CLIENTS NUMBER_LIST;

  BEFORE STATEMENT
    IS
  BEGIN
    V_CLIENTS:= NUMBER_LIST();
  END BEFORE STATEMENT;

  AFTER EACH ROW
    IS
  BEGIN
    V_CLIENTS.EXTEND();
    V_CLIENTS(V_CLIENTS.COUNT) := :NEW.CLIENTID;
  END AFTER EACH ROW;

  AFTER STATEMENT IS
  BEGIN

    MERGE INTO CONTRACTS
    USING (
            SELECT CONTRACTID,
              CANDIDATE_ENDDATE AS ENDDATE
            FROM
              (SELECT CONTRACTS.CONTRACTID,
                 (TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
                 DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
               FROM CONTRACTS
               WHERE CONTRACTS.CLIENTID IN (SELECT * FROM TABLE(V_CLIENTS)))
            WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
    ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
    WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
      WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
  END AFTER STATEMENT;

END CONTRACT_ENDDATE_ADJUSTER;
/

उपरोक्त प्रविष्टियों को दोहराने के बाद, परिणाम समान होता है:

CONTRACTID  CLIENTID  STARTDATE  ENDDATE    
Break-Ring  1         11-MAY-56  18-FEB-57  
GoBackHome  1         19-FEB-57  02-MAY-57  
Gardening   1         03-MAY-57             
SaveGalaxy  2         15-JUN-77  14-NOV-80  
DefendHoth  2         15-NOV-80  08-MAR-83  
GoWedding   2         09-MAR-83             



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. यदि आपके पास Oracle 11g है तो क्या PL/SQL सीखने की भाषा है?

  2. JDBC का उपयोग करके जावा से Oracle डेटाबेस पार्सर का उपयोग करना

  3. लाखों पंक्तियों वाली तालिका के साथ ऑरैकल में यादृच्छिक पंक्तियों का चयन कैसे करें?

  4. Oracle क्लाइंट के बिना Python Oracle DB कनेक्ट

  5. SQL संग्रहीत कार्यविधि तालिका में मान हाँ/नहीं की जाँच करने और sql निष्पादित करने के लिए