Oracle auto generated check constraint - oracle

When I create table with columns not null, Oracle automatically creating check constraints to be not null: like this ( query from user_constraints view)
NAME TYPE SEARCH_CONDITION
------------------------------ ---- ---------------------------------------
SYS_C0036357 C "SUPPLIER_ID" IS NOT NULL
SYS_C0036358 C "SUPPLIER_NAME" IS NOT NULL
So, is there any way to know that constraint created by Oracle(Auto) or it had been created by user.
thank you.

You can look at the GENERATED field in the user_constraints table (or all_constraints).
create table t (a number not null, constraint t_pk primary key(a));
select table_name, constraint_name, generated
from user_constraints
where table_name = 'T';
Gives:
T | CONSTRAINT. | GENERATED
----------------------------
T | SYS_C008425 | GENERATED NAME
T | T_PK | USER NAME

Related

How to CREATE TABLE AS adding an identity?

In such way I can create table from a table adding a column number:
drop table A_TEST
/
CREATE TABLE A_TEST AS
SELECT CAST( null as NUMBER ) as ROW_ID,
C_CODE,B_CODE
FROM A
However I want to add the column as an identity how to do that ? I tried the below, but throwing an error:
CREATE TABLE A_TEST AS
SELECT CAST( null as NUMBER GENERATED BY DEFAULT AS IDENTITY ) as ROW_ID,
C_CODE,B_CODE
FROM A
You can not create the table using CTAS including the IDENTITY column.
But, You can simply create a table without an identity column using CTAS and then ALTER the table to include IDENTITY columns as following:
CREATE TABLE A_TEST
AS
SELECT
C_CODE,
B_CODE
FROM
A;
ALTER TABLE A_TEST ADD ROW_ID NUMBER
GENERATED BY DEFAULT AS IDENTITY;
Cheers!!
Do it in multiple steps: create the table from the other table without data; then alter the table to add the identity column; and finally insert the data.
Oracle Setup:
CREATE TABLE A ( A_CODE, B_CODE, C_CODE ) AS
SELECT 999, 'BBB', SYSDATE FROM DUAL UNION ALL
SELECT 0, NULL, DATE '1970-01-01' FROM DUAL;
Create Table:
Create the table without the IDENTITY column and with no rows:
CREATE TABLE A_TEST AS
SELECT C_CODE, B_CODE
FROM A
WHERE 1 = 0;
Then alter the table to add the IDENTITY column:
ALTER TABLE A_TEST ADD (
ROW_ID NUMBER
GENERATED ALWAYS AS IDENTITY
CONSTRAINT A_TEST__ROW_ID__PK PRIMARY KEY
);
Then insert the rows:
INSERT INTO A_TEST ( C_CODE, B_CODE )
SELECT C_CODE, B_CODE FROM A;
(Or you can create the table and insert the rows in the first step; and alter the table to add the identity column without a NOT NULL/PRIMARY KEY constraint in the second step; and, if you want to add a NOT NULL/PRIMARY KEY constraint afterwards then it must be done in a separate subsequent ALTER TABLE statement. db<>fiddle)
Output:
SELECT * FROM A_TEST;
C_CODE | B_CODE | ROW_ID
:------------------ | :----- | -----:
2019-12-19 09:06:27 | BBB | 1
1970-01-01 00:00:00 | null | 2
db<>fiddle here

How to delete the primary key from without using constraint name

CREATE TABLE Persons (
ID int PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int
);
How to remove the primary key as there is no constraint defined?
"How to remove PK as there is no constraint defined?"
Actually it's every bit as simple as you might hope:
SQL> create table t23 (id number primary key);
Table created.
SQL> select constraint_name, constraint_type
2 from user_constraints
3 where table_name = 'T23'
4 /
CONSTRAINT_NAME C
------------------------------ -
SYS_C0034419 P
SQL> alter table t23 drop primary key;
Table altered.
SQL> select constraint_name, constraint_type
2 from user_constraints
3 where table_name = 'T23'
4 /
no rows selected
SQL>
run this to get constraint name :
SELECT *
FROM user_cons_columns
WHERE table_name = Persons;
then run
ALTER TABLE Persons
DROP CONSTRAINT <pk constraint>;
Don't think you can do it in 1 SQL command,without knowing the constraint name, but you can know the constraint name as in this case it would be defined by system. Something which starts with SYS.....
Alternatively you can use a PLSQL block to achieve the same.
See the example below for your case.
CREATE TABLE Persons (
ID int PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int
);
Find constraint name
select CONSTRAINT_NAME
From USER_CONSTRAINTS
where table_name='PERSONS'
AND CONSTRAINT_TYPE='P';
OUTPUT:= SYS_C0012152
Drop Constraint
ALTER TABLE PERSONS
DROP CONSTRAINT SYS_C0012152;
Note: The constraint name SYS_C0012152 is not enclosed in single quotes.
PLSQL Block to do the same
declare
sql_stmt varchar2(255);
cons_name varchar2(30);
begin
select CONSTRAINT_NAME
into cons_name
From USER_CONSTRAINTS
where table_name='PERSONS'
AND CONSTRAINT_TYPE='P';
sql_stmt:=' ALTER TABLE PERSONS
DROP CONSTRAINT '||cons_name;
dbms_output.put_line(sql_stmt);
execute immediate sql_stmt;
end;

How to add primary key constraint on oracle?

CREATE TABLE buses(Bus_no NUMBER(11) NOT NULL ,Bus_name Varchar2(20),Type VARCHAR2(20),Total_seats Number(11),Avail_seats Number(11));
ALTER TABLE buses
ADD CONSTRAINT PK_BUSES UNIQUE(Bus_no);
This is the table I need to create .. and this should be the output:
Name Null? Type
----------------------------------------- -------- ----------------------------
BUS_NO NOT NULL NUMBER(11)
BUS_NAME VARCHAR2(20)
TYPE VARCHAR2(20)
TOTAL_SEATS NUMBER(11)
AVAIL_SEATS NUMBER(11)
CONSTRAINT_NAME
------------------------------
PK_BUSES
However I am getting this extra line SYS-C00403053 along with my output table,please help to remove this.
CONSTRAINT_NAME
------------------------------
SYS_C00403053
PK_BUSES
You haven't added a primary key, you've added a unique constraint. While a unique constraint and a not-null constraint are effectively the same, they are not actually the same as an actual primary key.
As #GurwinderSingh said, the SYS_C00403053 is a system-generated name for the not-null constraint. It is possible, but unusual, to name a not-null constraint:
-- just to clean up what you have in the question, remove the unique constraint
ALTER TABLE buses DROP CONSTRAINT PK_BUSES;
ALTER TABLE buses MODIFY Bus_no NULL;
ALTER TABLE buses MODIFY Bus_no CONSTRAINT BUS_NO_NOT_NULL NOT NULL;
desc buses
Name Null? Type
----------- -------- ------------
BUS_NO NOT NULL NUMBER(11)
BUS_NAME VARCHAR2(20)
TYPE VARCHAR2(20)
TOTAL_SEATS NUMBER(11)
AVAIL_SEATS NUMBER(11)
select constraint_name, constraint_type, search_condition
from user_constraints where table_name = 'BUSES';
CONSTRAINT_NAME C SEARCH_CONDITION
------------------------------ - --------------------------------------------------------------------------------
BUS_NO_NOT_NULL C "BUS_NO" IS NOT NULL
But as you want a primary key anyway, you can drop the separate not-null check, as it's implied by a (proper) primary key:
ALTER TABLE buses MODIFY Bus_no NULL;
ALTER TABLE buses ADD CONSTRAINT PK_BUSES PRIMARY KEY (Bus_no);
desc buses
Name Null? Type
----------- -------- ------------
BUS_NO NOT NULL NUMBER(11)
BUS_NAME VARCHAR2(20)
TYPE VARCHAR2(20)
TOTAL_SEATS NUMBER(11)
AVAIL_SEATS NUMBER(11)
select constraint_name, constraint_type, search_condition
from user_constraints where table_name = 'BUSES';
CONSTRAINT_NAME C SEARCH_CONDITION
------------------------------ - --------------------------------------------------------------------------------
PK_BUSES P
You now only see the primary key constraint listed, but the column is still marked as not nullable, and you get the same error if you try to insert null:
insert into buses (bus_no) values (null);
ORA-01400: cannot insert NULL into ("MY_SCHEMA"."BUSES"."BUS_NO")
SYS_C00403053 is the system generated name given to the NOT NULL constraint on Bus_no column. Your result is as expected only.

where oracle foreign key constraint named SYS_C comming from

my database is oracle 10.2 and my create table sql is like this:
create table T_EP_SYS_COMPANY
(
company_id NUMBER not null,
company_name VARCHAR2(30),
company_address VARCHAR2(100),
is_in_use VARCHAR2(1),
is_canceled VARCHAR2(1),
is_headquarter VARCHAR2(1),
account_id NUMBER not null
)
tablespace USERS
pctfree 10
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
alter table T_EP_SYS_COMPANY
add constraint PK_ESHOP_SYS_COMPANY primary key (COMPANY_ID)
using index
tablespace USERS
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);
alter table T_EP_SYS_COMPANY
add constraint FK_SYS_COMPANY_PAY_ACCOUNT foreign key (ACCOUNT_ID)
references T_EP_PAY_ACCOUNT (ACCOUNT_ID);
but in my database,I have to 2 FKs on column "account_id":
owner constraint_name table_name column_name position
ESHOPV2 SYS_C009725 T_EP_SYS_COMPANY ACCOUNT_ID null
ESHOPV2 FK_SYS_COMPANY_PAY_ACCOUNT T_EP_SYS_COMPANY ACCOUNT_ID 1
why there are 2 FKs? I did rename the table name,dose the rename ddl has something to do with this?
They aren't both foreign key constraints. The SYS_C is a system-generated name for a constraint you didn't explicitly name; in this case for your not-null check. You can see those immediately after the create:
create table T_EP_SYS_COMPANY
(
company_id NUMBER not null,
company_name VARCHAR2(30),
company_address VARCHAR2(100),
is_in_use VARCHAR2(1),
is_canceled VARCHAR2(1),
is_headquarter VARCHAR2(1),
account_id NUMBER not null
);
select uc.constraint_name, uc.constraint_type, ucc.column_name, ucc.position
from user_constraints uc
join user_cons_columns ucc on ucc.constraint_name = uc.constraint_name
where uc.table_name = 'T_EP_SYS_COMPANY';
CONSTRAINT_NAME CONSTRAINT_TYPE COLUMN_NAME POSITION
------------------------------ --------------- --------------- --------
SYS_C0093988 C COMPANY_ID
SYS_C0093989 C ACCOUNT_ID
The constraint type is C, showing it's a check constraint. You can name those by explicitly adding check constraints rather than specifying them as 'not null' but there is no real benefit - you don't ever need to refer to them by name, e.g. to temporarily disable them.
After you add the primary and foreign key you see those too:
alter table T_EP_SYS_COMPANY
add constraint PK_ESHOP_SYS_COMPANY primary key (COMPANY_ID);
alter table T_EP_SYS_COMPANY
add constraint FK_SYS_COMPANY_PAY_ACCOUNT foreign key (ACCOUNT_ID)
references T_EP_PAY_ACCOUNT (ACCOUNT_ID);
select uc.constraint_name, uc.constraint_type, ucc.column_name, ucc.position
from user_constraints uc
join user_cons_columns ucc on ucc.constraint_name = uc.constraint_name
where uc.table_name = 'T_EP_SYS_COMPANY';
CONSTRAINT_NAME CONSTRAINT_TYPE COLUMN_NAME POSITION
------------------------------ --------------- --------------- --------
SYS_C0093988 C COMPANY_ID
SYS_C0093989 C ACCOUNT_ID
PK_ESHOP_SYS_COMPANY P COMPANY_ID 1
FK_SYS_COMPANY_PAY_ACCOUNT R ACCOUNT_ID 1
These have constraint type P and R, for 'primary key' and 'referential integrity'.
Read more about types of integrity constraints and how they are shown in the data dictionary.
owner constraint_name table_name column_name position
ESHOPV2 SYS_C009725 T_EP_SYS_COMPANY ACCOUNT_ID null
ESHOPV2 FK_SYS_COMPANY_PAY_ACCOUNT T_EP_SYS_COMPANY ACCOUNT_ID 1
why there are 2 FKs?
SYS_C009725 is not a foreign key constraint. It is a CHECK constraint for the NOT NULL condition. If you see the CONSTRAINT_TYPE then you would see it as C. And the name as SYS_C you see is because it is system-generated name.
Too keep it simple, let's see a small example:
SQL> CREATE TABLE t(
2 ID NUMBER NOT NULL
3 );
Table created.
SQL>
SQL> SELECT constraint_name,
2 constraint_type,
3 table_name,
4 search_condition
5 FROM user_constraints
6 WHERE table_name ='T';
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION
--------------- --------------- ---------- ----------------
SYS_C0010726 C T "ID" IS NOT NULL
SQL>

How can I store NULLs in NOT NULL field?

I just came across NULL values in NOT-NULL fields in our test database. How could they get there? I know that NOT-NULL constraints can be altered with NOVALIDATE clause, but that would change table's last_ddl_time in USER_OBJECTS. And that time is less than the date that those records were created. Is there something else I'm overlooking? Or is that someone's manual work for sure?
Table is partitioned and index-organized if that is relevant.
Oracle version is 9.2
The NOT NULL column condition is not like other constraints: you can disable a NOT NULL constraint but the column won't be considered NOT NULL if you reenable the constraint with NOVALIDATE. Let's build a small example:
SQL> CREATE TABLE tt (ID NUMBER NOT NULL);
Table created
SQL> SELECT column_name, nullable FROM user_tab_columns WHERE table_name = 'TT';
COLUMN_NAME NULLABLE
------------------------------ --------
ID N
now if I disable the constraint and reenable it with NOVALIDATE, the column won't be considered NOT NULLABLE by Oracle:
SQL> SELECT constraint_name, search_condition
2 FROM user_constraints WHERE table_name = 'TT';
CONSTRAINT_NAME SEARCH_CONDITION
------------------------------ ----------------------------
SYS_C00786538 "ID" IS NOT NULL
SQL> ALTER TABLE tt MODIFY CONSTRAINT SYS_C00786538 DISABLE;
Table altered
SQL> ALTER TABLE tt MODIFY CONSTRAINT SYS_C00786538 ENABLE NOVALIDATE;
Table altered
SQL> SELECT column_name, nullable FROM user_tab_columns WHERE table_name = 'TT';
COLUMN_NAME NULLABLE
------------------------------ --------
ID Y
So, I would say that if you have NULL values in a NOT NULLABLE column (as per my last query) you have a bug (contact support?)
Check If the constraint are suspended / Disabled
And you're sure these columns are really null? In other words:
SELECT field
FROM your_table
WHERE not_null_field IS NULL;
returns rows? Perhaps they've just got non-displayable data...

Resources