Class Exer,CHAPTER 13 -- ALTERING TABLES (COLUMNS and CONSTRAINTS) ================================================================= SQL> SET PAGESIZE 200 SQL> SELECT TNAME FROM TAB; TNAME -----------------------------BIN$HS7ZCdo/azLgQKjAUQJLcw==$0 BIN$HS7ZCdo3azLgQKjAUQJLcw==$0 BIN$HS7ZCdoYazLgQKjAUQJLcw==$0 BIN$HS7ZCdofazLgQKjAUQJLcw==$0 BIN$HS7ZCdokazLgQKjAUQJLcw==$0 BIN$HS7ZCdoyazLgQKjAUQJLcw==$0 BIN$HTBCOUh5/rzgQKjAUQJSOw==$0 BIN$HTBCOUiA/rzgQKjAUQJSOw==$0 BIN$HTBCOUiF/rzgQKjAUQJSOw==$0 BIN$HTBCOUiT/rzgQKjAUQJSOw==$0 COUNTRIES CUST DEPART DEPARTMENTS EMPL EMPLOYEES JOB_GRADES JOB_HISTORY LOCATIONS MY_EMPLOYEE PREVIOUSLY REMOVED (DROPPED) TABLES BUT NOT PURGED YET 20 rows selected. SQL> DESC depart Name ----------------------------------------DEPT# DNAME CITY SQL> DESC empl Name ----------------------------------------EMP# LNAME FNAME PAY SDATE JOB DEPT# Null? -------NOT NULL NOT NULL Null? -------NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL Type -------------------NUMBER(4) VARCHAR2(25) VARCHAR2(20) Type -------------------NUMBER(7) VARCHAR2(20) VARCHAR2(20) NUMBER(7,2) DATE VARCHAR2(15) NOT NULL NUMBER(4) SQL> DESC cust Name ----------------------------------------CUST# CUSTNAME CITY RATING COMMENTS SALESREP# Null? -------NOT NULL NOT NULL NOT NULL Type -------------------NUMBER(6) VARCHAR2(30) VARCHAR2(20) CHAR(1) VARCHAR2(200) NUMBER(7) SQL> ALTER TABLE depart 2 ADD COLUMN (PROVINCE CHAR(2) NOT NULL); ADD COLUMN (PROVINCE CHAR(2) NOT NULL) * ERROR at line 2: ORA-00904: : invalid identifier you must NOT use word COLUMN here SQL> ALTER TABLE depart 2* ADD (PROVINCE CHAR(2) NOT NULL); ALTER TABLE depart * ERROR at line 1: ORA-01758: table must be empty to add mandatory (NOT NULL) column SQL> ALTER TABLE depart 2* ADD (PROVINCE CHAR(2)); Table altered. to non-empty tables you may add only optional columns SQL> ALTER TABLE empl 2 MODIFY (sdate NULL); Table altered. it is always possible to declare a mandatory column to become optional SQL>ALTER TABLE empl 2* MODIFY (job VARCHAR2(20)); Table altered. it is always possible to increase the column length SQL> ALTER TABLE empl 2* MODIFY (job VARCHAR2(12)); Table altered. it is possible to decrease the column length up to the value that no existing column value will go over SQL> ALTER TABLE cust 2 SET UNUSED comments; SET UNUSED comments * ERROR at line 2: ORA-00905: missing keyword here you must use word COLUMN SQL> ALTER TABLE cust 2* SET UNUSED COLUMN comments ; Table altered. SQL> SELECT custname, comments FROM cust; SELECT custname, comments FROM cust * ERROR at line 1: ORA-00904: "COMMENTS": invalid identifier after column has been unset, it is promptly removed logically from the dictionary, but it must be later also physically removed from disk SQL> ALTER TABLE cust 2 DROP UNUSED COLUMNS; Table altered. SQL> DESC depart Name ----------------------------------------DEPT# DNAME CITY PROVINCE SQL> DESC empl Name ----------------------------------------EMP# LNAME FNAME PAY SDATE JOB DEPT# SQL> DESC cust Name ----------------------------------------CUST# CUSTNAME CITY RATING SALESREP# Null? -------NOT NULL NOT NULL Type -------------------NUMBER(4) VARCHAR2(25) VARCHAR2(20) CHAR(2) Null? -------NOT NULL NOT NULL NOT NULL NOT NULL Type -------------------NUMBER(7) VARCHAR2(20) VARCHAR2(20) NUMBER(7,2) DATE VARCHAR2(12) NOT NULL NUMBER(4) Null? -------NOT NULL NOT NULL NOT NULL Type -------------------NUMBER(6) VARCHAR2(30) VARCHAR2(20) CHAR(1) NUMBER(7) SQL> SELECT * FROM depart; DEPT# ---------10 90 190 20 60 50 DNAME ------------------------Administration Executive Contracting Marketing IT Shipping CITY PR -------------------- -Seattle Seattle Seattle Toronto Southlake South San Francisco 6 rows selected. SQL> ALTER TABLE depart 2 MODIFY (city NOT NULL); Table altered. it is possible to declare an optional column to become a mandatory one if there is NO blank value in that column SQL> INSERT INTO depart (dept#, dname) VALUES (200,'HR'); INSERT INTO depart (dept#, dname) VALUES (200,'HR') * ERROR at line 1: ORA-01400: cannot insert NULL into ("OA301A40"."DEPART"."CITY") you must insert values into ALL MANDATORY columns (here is City column without value and it is previously declared as a mandatory column) SQL> INSERT INTO depart (dept#, dname,city) VALUES (200,'HR','CHICAGO'); 1 row created. SQL> 2 3 SET UPDATE empl SET job = 'Database Analyst' WHERE UPPER(lname) = 'ERNST' ; job = 'Database Analyst' * ERROR at line 2: ORA-12899: value too large for column "OA301A40"."EMPL"."JOB" (actual: 16, maximum: 12) SQL> ALTER TABLE empl 2 MODIFY (job VARCHAR2(16) ); Table altered. if you increase the column length then you can modify data accordingly SQL> UPDATE empl 2 SET job = 'Database Analyst' 3 WHERE UPPER(lname) = 'ERNST'; 1 row updated. SQL> RENAME depart TO dep; Table renamed. you can always rename any database object (table, view, index etc.) SQL> SELECT * FROM empl 2 WHERE UPPER(lname) = 'ERNST'; EMP# LNAME FNAME PAY SDATE ---------- -------------------- -------------------- ---------- -------JOB DEPT# ---------------- ---------104 Ernst Bruce 6000 21-MAY-91 Database Analyst 60 SQL> REM Other session that I opened also showed "Database Analyst" because RENAME (as DDL command) performs AUTO-COMMIT firstly SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 701 Enter value for custname: BLUE SKY LTD Enter value for city: Vancouver Enter value for rating: B Enter value for rep: 102 old 1: INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep) new 1: INSERT INTO cust VALUES (701,'BLUE SKY LTD','Vancouver','B',102) 1 row created. SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 702 Enter value for custname: MIKE and SAM inc. Enter value for city: Kingston Enter value for rating: A Enter value for rep: 107 old 1: INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep) new 1: INSERT INTO cust VALUES (702,'MIKE and SAM inc.','Kingston','A',107) 1 row created. SQL> SET VERIFY OFF to get rid of old and new lines SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 703 Enter value for custname: RED PLANET Enter value for city: Mississauga Enter value for rating: C Enter value for rep: 107 1 row created. SQL> COMMIT; Commit complete. SQL> SELECT * FROM cust; CUST# ---------701 703 702 501 502 503 CUSTNAME CITY R SALESREP# ------------------------------ ----------------------------BLUE SKY LTD Vancouver B 102 RED PLANET Mississauga C 107 MIKE and SAM inc. Kingston A 107 ABC LTD. Montreal C 201 Black Giant Ottawa B 202 Mother Goose London B 202 6 rows selected. SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 717 Enter value for custname: BLUE SKY LTD Enter value for city: Regina same Customer Name, but different city Enter value for rating: D Enter value for rep: 102 1 row created. SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 718 Enter value for custname: Black Giant Enter value for city: Ottawa Enter value for rating: A Enter value for rep: 202 INSERT INTO cust VALUES (718,'Black Giant','Ottawa','A',202) * ERROR at line 1: ORA-00001: unique constraint (OA301A40.CUST_CUSTNAME_CITY_UK) violated there is a composite UNIQUE constraint on CustName and City, so that you can NOT have a same customer name twice in the same city (look in the table creation script in the Chap9 practice) SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 720 Enter value for custname: Big Mouse Enter value for city: Toronto Enter value for rating: F Enter value for rep: 202 INSERT INTO cust VALUES (720,'Big Mouse','Toronto','F',202) * ERROR at line 1: ORA-02290: check constraint (OA301A40.CUST_RATING_CK) violated there is a CHECK constraint on column Rating that allows only values from set {A,B,C,D} to be entered (but not F) SQL> INSERT INTO cust VALUES (&custno,'&custname','&city','&rating',&rep); Enter value for custno: 721 Enter value for custname: Big Mouse Enter value for city: Toronto Enter value for rating: D Enter value for rep: 108 INSERT INTO cust VALUES (721,'Big Mouse','Toronto','D',108) * ERROR at line 1: ORA-02291: integrity constraint (OA301A40.CUST_SALESREP#_FK) violated parent key not found there is a FOREIGN KEY constraint on column SalesRep# that allows only values from the set of values for Emp# column in the parent table EMPL to be entered (and 108 does not exist as an employee there) SQL> COMMIT; Commit complete. SQL> SELECT * FROM cust; CUST# ---------701 703 717 702 501 502 503 CUSTNAME CITY R SALESREP# ------------------------------ -------------------- - ------BLUE SKY LTD Vancouver B 102 RED PLANET Mississauga C 107 BLUE SKY LTD Regina D 102 MIKE and SAM inc. Kingston A 107 ABC LTD. Montreal C 201 Black Giant Ottawa B 202 Mother Goose London B 202 7 rows selected. SQL> SELECT constraint_name, constraint_type, search_condition, status FROM user_constraints WHERE table_name = ‘CUST’ ORDER BY 2; CONSTRAINT_NAME CON SEARCH_CONDITION STATUS SYS_C0070132 C "CUSTNAME" IS NOT NULL ENABLED SYS_C0070133 C "CITY" IS NOT NULL ENABLED CUST_RATING_CK C Rating IN ('A','B','C','D') ENABLED CUST_CUST#_PK P ENABLED CUST_SALESREP#_FK R ENABLED CUST_CUSTNAME_CITY_UK U ENABLED 6 rows selected. This is the query you may use to find out what constraints are declared for a table and what is their status and for CHECK (C) constraints only what is their search condition. SQL> ALTER TABLE cust DISABLE CONSTRAINT cust_salesrep#_fk; Table altered. SQL> UPDATE cust SET salesrep# = 108 WHERE cust# = 501; non-existing value in table EMPL 1 row updated. The FK constraint is turned off (disabled) and we can put for salesrep# any value we want (and 108 does not exist in a table EMPL) SQL> ALTER TABLE cust ENABLE CONSTRAINT ALTER TABLE cust ENABLE CONSTRAINT cust_salesrep#_fk; cust_salesrep#_fk * ERROR at line 1: ORA-02298: cannot validate (OA301B40.CUST_SALESREP#_FK) - parent keys not found As any DDL statement, ALTER TABLE firstly auto-commits anything not saved before and then tries to execute itself (so 108 is saved as Salesrep# firstly and then it was made an attempt to enable this constraint that failed, because it had “violation” in that one row) SQL> UPDATE cust SET salesrep# = 107 WHERE cust# = 501; 1 row updated. existing value in table EMPL SQL> ALTER TABLE cust ENABLE CONSTRAINT cust_salesrep#_fk; Table altered. After fixing the row that caused the violation, the constraint can be enabled (this is valid for any constraint type) SQL> ALTER TABLE cust DROP CONSTRAINT cust_rating_ck ; Table altered. You can NOT modify the constraint definition, but you need to drop and add it again with the new definition (here we will add F to the set of values for column Rating) SQL> ALTER TABLE cust ADD CONSTRAINT cust_rating_ck CHECK (rating IN ('A','B','C','D','F')) ; Table altered. SQL> SELECT constraint_name, constraint_type, search_condition, status FROM user_constraints WHERE table_name = ‘DEP’ ORDER BY 2; CONSTRAINT_NAME SYS_C0070121 CON SEARCH_CONDITION C "DNAME" IS NOT NULL STATUS ENABLED SYS_C0070138 C ENABLED DEPART_DEPT#_PK P ENABLED DEPART_DNAME_UK U ENABLED SQL> ALTER TABLE dep "CITY" IS NOT NULL DROP CONSTRAINT depart_dname_uk ; Table altered. Let’s change the UK constraint from single to composite one, so that you can have only one department name in the same city. SQL> ALTER TABLE dep ADD CONSTRAINT dep_dname_uk UNIQUE (dname, city); Table altered.