Hello everyone i am new to databases and i am trying to make add a foreign key the first time i tried i had the following error
ORA-01735: invalid ALTER TABLE option when i googled it it found something like DEFAULT NULL: But when i use it i get the Following error code RA-00904: : invalid identifier
My alter Table looks like this
alter table car
add constraint priceCar DEFAULT NULL foreign key (note) references priceCode(note) DEFAULT NULL;
I dont know what i am doing wrong this is my first time using databases Oracle
Adding the constraint would just be:
alter table car
add constraint priceCar foreign key (note) references priceCode(note);
assuming the relevant column already exists in both tables and is the same data type, and is a primary or unique key in priceCode.
The default value for a column is a completely unrelated issue, and as this is presumably a number column it will default to null anyway. You can explicitly add a default null clause to the column definition (not the constraint) but you don't need to.
Quick demo with made-up tables:
create table pricecode(note number primary key);
Table PRICECODE created.
create table car (id number, note number);
Table CAR created.
alter table car
add constraint priceCar foreign key (note) references priceCode(note);
Table CAR altered.
insert into car (id) values (1);
1 row inserted.
Then:
select * from car;
ID NOTE
---------- ----------
1
shows that note defaulted to null without you having to explicitly set that up (and also that it didn't complain about it not matching any primary key value).
Related
The following code creates a table without raising any errors:
CREATE TABLE test(
ID INTEGER NULL,
CONSTRAINT PK_test PRIMARY KEY(ID)
)
Note that I cannot insert a NULL, as expected:
INSERT INTO test
VALUES(1),(NULL)
ERROR: null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null).
********** Error **********
ERROR: null value in column "id" violates not-null constraint
SQL state: 23502
Detail: Failing row contains (null).
Why can I create a table with a self-contradictory definition? ID column is explicitly declared as NULLable, and it is not implicitly nullable, as a part of the PRIMARY KEY. Does it make sense?
Edit: would it not be better if this self-contradictory CREATE TABLE just failed right there?
Because the PRIMARY KEY makes the included column(s) NOT NULL automatically. I quote the manual here:
The primary key constraint specifies that a column or columns of a
table can contain only unique (non-duplicate), nonnull values.
Technically, PRIMARY KEY is merely a combination of UNIQUE and NOT NULL.
Bold emphasis mine.
I ran a test to confirm that NOT NULL is completely redundant in combination with a PRIMARY KEY constraint (in the current implementation, retested in version 13). The NOT NULL constraint stays even after dropping the PK constraint, irregardless of an explicit NOT NULL clause at creation time.
CREATE TABLE foo (foo_id int PRIMARY KEY);
ALTER TABLE foo DROP CONSTRAINT foo_pkey;
db=# \d foo
table »public.foo«
column | type | attribute
--------+---------+-----------
foo_id | integer | not null -- stays
db<>fiddle here
Identical behavior if NULL is included in the CREATE TABLE statement.
It still won't hurt to keep NOT NULL redundantly in code repositories if the column is supposed to be NOT NULL. If you later decide to alter the PK constraint, you might forget to mark the column NOT NULL - or whether it even was supposed to be NOT NULL.
There is an item in the Postgres TODO wiki to decouple NOT NULL from the PK constraint. So this might change in future versions:
Move NOT NULL constraint information to pg_constraint
Currently NOT NULL constraints are stored in pg_attribute without any designation of their origins, e.g. primary keys. One manifest
problem is that dropping a PRIMARY KEY constraint does not remove the
NOT NULL constraint designation. Another issue is that we should
probably force NOT NULL to be propagated from parent tables to
children, just as CHECK constraints are. (But then does dropping
PRIMARY KEY affect children?)
Answer to added question
Would it not be better if this self-contradictory CREATE TABLE just
failed right there?
As explained above, this
foo_id INTEGER NULL PRIMARY KEY
is (currently) 100 % equivalent to:
foo_id INTEGER PRIMARY KEY
Since NULL is treated as noise word in this context.
And we wouldn't want the latter to fail. So this is not an option.
If memory serves, the docs mention that:
the null in create table statements is basically a noise word that gets ignored
the primary key forces a not null and a unique constraint
See:
# create table test (id int null primary key);
CREATE TABLE
# \d test
Table "public.test"
Column | Type | Modifiers
--------+---------+-----------
id | integer | not null
Indexes:
"test_pkey" PRIMARY KEY, btree (id)
If as #ErwinBrandstetter said, PRIMARY KEY is merely a combination of UNIQUE and NOT NULL, you can use an UNIQUE constraint without NOT NULL instead of PRIMARY KEY. Example:
CREATE TABLE test(
id integer,
CONSTRAINT test_id_key UNIQUE(id)
);
This way you can do things like:
INSERT INTO test (id) VALUES (NULL);
INSERT INTO test (id) VALUES (NULL);
INSERT INTO test (id) VALUES (NULL);
Speaking about NOT NULL, there are many ways to ensure it.
Not speaking only about PostgreSQL as a relational database engine:
Column constraint.
Table constraint (single NOT NULL or complex Boolean expression)
Index definition,
Triggers that change any NULL to "something else".
There may be even other methods.
One suffices. Not having the others means we have a contradiction? I do not think so.
A PRIMARY KEY column is forced to be NOT NULL.
The documentation says as shown below:
Adding a primary key will automatically create a unique B-tree index
on the column or group of columns listed in the primary key, and will
force the column(s) to be marked NOT NULL.
I am adding a new column in an existing table with preloaded data. This column uses a primary key from another table and I want to default this to 5. I have tried the following code:
ALTER TABLE group
ADD group_type INT
GO
ALTER TABLE group
ADD CONSTRAINT FK_group_type DEFAULT 5 FOR group_type
GO
I was expecting on alter of the group table then all the values will be filled with 5 but instead its NULL. What am I doing wrong?
First of all, adding a DEFAULT constraint (in it's own SQL statement) to a column does not effect existing data in that column. It only effects new INSERTS to that table which do not provide a value for that column.
Second, you haven't created a FOREIGN KEY constraint here.
EDIT:
Here would be one way to create the FK correctly
ALTER TABLE group
ADD group_type_id INT
GO
ALTER TABLE group
ADD CONSTRAINT fk_groupType FOREIGN KEY (group_type_id)
REFERENCES group_type (group_type_id)
This worked for me, it set the foreign key constraint, default value, and updated existing table records all in a single ALTER TABLE statement. I'm using a SQL Azure database (via SQL Management Studio), so, YMMV.
ALTER TABLE Group
ADD GroupTypeId int NOT NULL
CONSTRAINT DK_GroupTypeId DEFAULT (5) WITH VALUES
CONSTRAINT FK_GroupTypeId FOREIGN KEY
REFERENCES [dbo].[GroupType] (GroupTypeId)
GO
It took a while to run, but a subsequent select, showed the rows had the correct default value for those columns.
Disclaimer: I edited the above query from my table / key names to yours without re-testing it, so you may want to double check it for any typos or other mismatches; The syntax should be the same though.
You can use:
alter table [group]
add group_type int constraint df_group_type default (5) with values
However, it doesn't seem a good idea to use constant as a default value for a column, which is supposed to be FK column.
It seems, that may be what actually you are trying to do is following:
alter table [group] add column group_type int
GO
update [group] set group_type = (select id from group_type where desc ='typeA')
GO
alter table [group] add constraint FK_group_grouptype foreign key (group_type) references group_type (id)
GO
Adding default constraint will affect existing rows if you add new not nullable column to table.
ALTER TABLE group
ADD group_type INT NOT NULL
CONSTRAINT DK_group_type DEFAULT 5
GO
Newbie in need of help.
I'm creating a small database.
I want to constrain data in a couple of tables - Lender and Pingtree. The ProviderType table contains lookup data and contains either 'Lender' or 'Pingtree'. How can I modify this structure so that the Lender table only can contain Lender types and Pingtree, Pingtree types?
Guessing that ProviderTypeID is the column in the Provider table that distinguishes between the two types, then you must add this same column to both the Lender and Pingtree tables, add a suitable key (if it doesn't already exist) in Provider on ID, ProviderTypeId, and then add a composite FOREIGN KEY constraint to the Lender and Pingtree tables that include these columns.
While this may sound like a drag, it is a known pattern called supertyping/subtyping. When the supertype (Provider) can be multiple subtypes, you don't need the TypeId column. But when the subtypes are mutually exclusive, this is what you must do.
It might look something like this:
ALTER TABLE dbo.Lender ADD ProviderTypeId tinyint NOT NULL
CONSTRAINT DF_Lender_ProviderTypeID DEFAULT (1)
CONSTRAINT CK_Lender_ProviderTypeID_Is_Lender CHECK (ProviderTypeID = 1);
ALTER TABLE dbo.Pingtree ADD ProviderTypeId tinyint NOT NULL
CONSTRAINT DF_Pingtree_ProviderTypeID DEFAULT (2)
CONSTRAINT CK_Pingtree_ProviderTypeID_Is_Pingtree CHECK (ProviderTypeID = 2);
-- Any of a PK, UNIQUE constraint, or unique index will do
ALTER TABLE dbo.Provider ADD CONSTRAINT UQ_Provider_ID_ProviderTypeID
UNIQUE (ID, ProviderTypeID);
ALTER TABLE dbo.Lender DROP CONSTRAINT FK_Lender_ProviderId;
ALTER TABLE dbo.Lender ADD CONSTRAINT FK_Lender_ProviderId_ProviderTypeId
FOREIGN KEY (ID, ProviderTypeID) REFERENCES dbo.Provider (ID, ProviderTypeID);
ALTER TABLE dbo.PingTree DROP CONSTRAINT FK_PingTree_ProviderId;
ALTER TABLE dbo.PingTree ADD CONSTRAINT FK_PingTree_ProviderId_ProviderTypeId
FOREIGN KEY (ID, ProviderTypeID) REFERENCES dbo.Provider (ID, ProviderTypeID);
If written correctly (specifying the column list on INSERT) your stored procedures and application SQL code should not have to change.
I have two tables, Table JOB and Table USER, here is the structure
CREATE TABLE JOB
(
ID NUMBER NOT NULL ,
USERID NUMBER,
CONSTRAINT B_PK PRIMARY KEY ( ID ) ENABLE
);
CREATE TABLE USER
(
ID NUMBER NOT NULL ,
CONSTRAINT U_PK PRIMARY KEY ( ID ) ENABLE
);
Now, i want to add foreign key constraint to JOB referencing to USER table, as
Alter Table JOB ADD CONSTRAINT FK_USERID FOREIGN KEY(USERID) REFERENCES USER(ID);
this throws Oracle (ORA-02270) : no matching unique or primary key for this column-list error, doing some investigation it appears that we need to have either unique key or primary key constraint on USERID but I cannot have that as one USERID can have multiple JOBS associated with him, any thoughts or suggestions on how to fix this issue?
Researched ORA-02270 and SO related question
The ORA-2270 error is a straightforward logical error: it happens when the columns we list in the foreign key do not match a primary key or unique constraint on the parent table. Common reasons for this are
the parent lacks a PRIMARY KEY or UNIQUE constraint altogether
the foreign key clause references the wrong column in the parent table
the parent table's constraint is a compound key and we haven't referenced all the columns in the foreign key statement.
Neither appears to be the case in your posted code. But that's a red herring, because your code does not run as you have posted it. Judging from the previous edits I presume you are not posting your actual code but some simplified example. Unfortunately in the process of simplification you have eradicated whatever is causing the ORA-2270 error.
SQL> CREATE TABLE JOB
(
ID NUMBER NOT NULL ,
USERID NUMBER,
CONSTRAINT B_PK PRIMARY KEY ( ID ) ENABLE
); 2 3 4 5 6
Table created.
SQL> CREATE TABLE USER
(
ID NUMBER NOT NULL ,
CONSTRAINT U_PK PRIMARY KEY ( ID ) ENABLE
); 2 3 4 5
CREATE TABLE USER
*
ERROR at line 1:
ORA-00903: invalid table name
SQL>
That statement failed because USER is a reserved keyword so we cannot name a table USER. Let's fix that:
SQL> 1
1* CREATE TABLE USER
SQL> a s
1* CREATE TABLE USERs
SQL> l
1 CREATE TABLE USERs
2 (
3 ID NUMBER NOT NULL ,
4 CONSTRAINT U_PK PRIMARY KEY ( ID ) ENABLE
5* )
SQL> r
1 CREATE TABLE USERs
2 (
3 ID NUMBER NOT NULL ,
4 CONSTRAINT U_PK PRIMARY KEY ( ID ) ENABLE
5* )
Table created.
SQL> Alter Table JOB ADD CONSTRAINT FK_USERID FOREIGN KEY(USERID) REFERENCES USERS(ID);
Table altered.
SQL>
And lo! No ORA-2270 error.
Alas, there's not much we can do here to help you further. You have a bug in your code. You can post your code here and one of us can spot your mistake. Or you can check your own code and discover it for yourself.
Note: an earlier version of the code defined HOB.USERID as VARCHAR2(20). Because USER.ID is defined as a NUMBER the attempt to create a foreign key would have hurl a different error:
ORA-02267: column type incompatible with referenced column type
An easy way to avoid mismatches is to use foreign key syntax to default the datatype of the column:
CREATE TABLE USERs
(
ID number NOT NULL ,
CONSTRAINT U_PK PRIMARY KEY ( ID ) ENABLE
);
CREATE TABLE JOB
(
ID NUMBER NOT NULL ,
USERID constraint FK_USERID references users,
CONSTRAINT B_PK PRIMARY KEY ( ID ) ENABLE
);
The data type in the Job table (Varchar2(20)) does not match the data type in the USER table (NUMBER NOT NULL).
In my case the problem was cause by a disabled PK.
In order to enable it:
I look for the Constraint name with:
SELECT * FROM USER_CONS_COLUMNS WHERE TABLE_NAME = 'referenced_table_name';
Then I took the Constraint name in order to enable it with the following command:
ALTER TABLE table_name ENABLE CONSTRAINT constraint_name;
We have the following script for create a new table:
CREATE TABLE new_table
(
id NUMBER(32) PRIMARY KEY,
referenced_table_id NUMBER(32) NOT NULL,
CONSTRAINT fk_new_table_referenced_table_id
FOREIGN KEY (referenced_table_id)
REFERENCES referenced_table (id)
);
and we were getting this error on execution:
[42000][2270] ORA-02270: no matching unique or primary key for this
column-list
The issue was due to disabled primary key of the referenced table in our case. We have to enable it using the following sql:
ALTER TABLE referenced_table ENABLE PRIMARY KEY USING INDEX;
after that we created new table using first script without any issues
The scheme is correct, User.ID must be the primary key of User, Job.ID should be the primary key of Job and Job.UserID should be a foreign key to User.ID. Also, your commands appear to be syntactically correct.
So what could be wrong? I believe you have at least a Job.UserID which doesn't have a pair in User.ID. For instance, if all values of User.ID are: 1,2,3,4,6,7,8 and you have a value of Job.UserID of 5 (which is not among 1,2,3,4,6,7,8, which are the possible values of UserID), you will not be able to create your foreign key constraint. Solution:
delete from Job where UserID in (select distinct User.ID from User);
will delete all jobs with nonexistent users. You might want to migrate these to a copy of this table which will contain archive data.
Most Probably when you have a missing Primary key is not defined from parent table. then It occurs.
Like Add the primary key define in parent as below:
ALTER TABLE "FE_PRODUCT" ADD CONSTRAINT "FE_PRODUCT_PK" PRIMARY KEY ("ID") ENABLE;
Hope this will work.
I faced the same issue in my scenario as follow:
I created textbook table first with
create table textbook(txtbk_isbn varchar2(13)
primary key,txtbk_title varchar2(40),
txtbk_author varchar2(40) );
Then chapter table:
create table chapter(txtbk_isbn varchar2(13),chapter_title varchar2(40),
constraint pk_chapter primary key(txtbk_isbn,chapter_title),
constraint chapter_txtbook foreign key (txtbk_isbn) references textbook (txtbk_isbn));
Then topic table:
create table topic(topic_id varchar2(20) primary key,topic_name varchar2(40));
Now when I wanted to create a relationship called chapter_topic between chapter (having composite primary key) and topic (having single column primary key), I faced issue with following query:
create table chapter_topic(txtbk_isbn varchar2(13),chapter_title varchar2(40),topic_id varchar2(20),
primary key (txtbk_isbn, chapter_title, topic_id),
foreign key (txtbk_isbn) references textbook(txtbk_isbn),
foreign key (chapter_title) references chapter(chapter_title),
foreign key (topic_id) references topic (topic_id));
The solution was to refer to composite foreign key as below:
create table chapter_topic(txtbk_isbn varchar2(13),chapter_title varchar2(40),topic_id varchar2(20),
primary key (txtbk_isbn, chapter_title, topic_id),
foreign key (txtbk_isbn, chapter_title) references chapter(txtbk_isbn, chapter_title),
foreign key (topic_id) references topic (topic_id));
Thanks to APC post in which he mentioned in his post a statement that:
Common reasons for this are
- the parent lacks a constraint altogether
- the parent table's constraint is a compound key and we haven't referenced all the columns in the foreign key statement.
- the referenced PK constraint exists but is DISABLED
When running this command:
ALTER TABLE MYTABLENAME MODIFY CONSTRAINT MYCONSTRAINTNAME_FK ENABLE;
I got this error:
ORA-02270: no matching unique or primary key for this column-list
02270. 00000 - "no matching unique or primary key for this column-list"
*Cause: A REFERENCES clause in a CREATE/ALTER TABLE statement
gives a column-list for which there is no matching unique or primary
key constraint in the referenced table.
*Action: Find the correct column names using the ALL_CONS_COLUMNS
The referenced table has a primary key constraint with matching type. The root cause of this error, in my case, was that the primary key constraint was disabled.
Isn't the difference between your declaration of USERID the problem
JOB: UserID is Varchar
USER: UserID is Number?
If primary key is not already defined on parent table then this issue may arise. Please try to define the primary key on existing table.
For eg:
ALTER TABLE table_name
ADD PRIMARY KEY (the_column_which_is_primary_key);
create table articles(code varchar2(30)constraint articles_pk primary key,titre varchar2(30),
support varchar2(30) constraint support_fk references supports(support),type_support varchar2(30),
numeroDePage varchar2(30),datepublication date,categorie varchar2(30)constraint categorie_fk references organismes(categorie),
tendance varchar2(30)constraint tendance_fk references apreciations(tendance));
I need to add a NOT NULL column to an existing (populated) table that will be a foreign key to another table. This brings about two problems:
When you add the column, its value cannot be null - using a default is not an option (unless it is removed later on) because the database logic is used in the server side validation when a user enters a new record i.e. when the application tries to add a record with this field having a null value, the database throws an error that the application catches and returns to the user, prompting them to correct it.
The column has a foreign key constraint, meaning its value MUST exist in the foreign table as well.
What is the best way to go about this?
Create the column, but allow NULL.
Populate the column with the correct data from the foreign key table.
Alter the column add not null.
Add the foreign key constraint.
About parts of your questions (ofc after years):
1.If you mean that the default value would be something so smart, and you wouldn`t need to change it in future, then your wish is wrong. why?
for two reasons:
a) In the concept of Default value (in every where programming
languages, DBs and so on...) the default value is not something which
replace the value dynamically with something you want. For
example Func Sum(a,b,c=10), in this situation if you don't enter parameter c, it would take it as 10, otherwise you should enter
something instead. so default values are predictable and calculable
values, NOT smart values.
b) Foreign keys are something even more sensitive than a optional
parameter in a method, coz of the relational meanings in RDBMSs so u
surely should edit that in future, even maybe sometimes it change
over and over base on usages of DB.
2.It can be handle with the code i`ll show you.
Therefore base on this explanations you could have a column with default value which exist in Fkeys, but it won`t be something you need, and you should update it in future base on your usage. and for this you need:
FIRST:
Create a function that return a valid and exist foreign key of
specific table like this:
CREATE FUNCTION SelectMinForeignKey()
RETURNS INT
AS
BEGIN
DECLARE #FirstID INT
SELECT #FirstID = MIN(ID) from DetailTableExample01
RETURN #FirstID
END
SECOND:
Then you should alter your table to add column like this:
ALTER TABLE example1 ADD NoNullableCol INT NOT NULL DEFAULT [dbo].SelectMinForeignKey()
or with adding Relation instantly:
ALTER TABLE example1
ADD NoNullableCol2 INT NOT NULL DEFAULT [dbo].SelectMinForeignKey() ,
FOREIGN KEY(NoNullableCol2) REFERENCES DetailTableExample01(id);
or more complete with adding constraint instantly and assignable FK name:
ALTER TABLE dbo.example1 ADD
NoNullableCol INT NOT NULL DEFAULT [dbo].SelectMinForeignKey(),
CONSTRAINT FK_example1_DetailTableExample01
FOREIGN KEY (NoNullableCol)
REFERENCES dbo.DetailTableExample01 (ID)
ON UPDATE CASCADE
ON DELETE CASCADE;
or:
ALTER TABLE dbo.example1 ADD
NoNullableCol INT NOT NULL DEFAULT [dbo].SelectMinForeignKey()
GO
ALTER TABLE dbo.example1 ADD
CONSTRAINT FK_example1_DetailTableExample01
FOREIGN KEY (NoNullableCol)
REFERENCES dbo.DetailTableExample01 (ID)
ON UPDATE CASCADE
ON DELETE CASCADE
NOTE: As you know table and column names are sample.
THIRD:
Now you should change values in NoNullableCol as you want
All-in-One:
The entire query would be something like this
CREATE FUNCTION SelectMinForeignKey()
RETURNS INT
AS
BEGIN
DECLARE #FirstID INT
SELECT #FirstID = MIN(ID) from DetailTableExample01
RETURN #FirstID
END
GO
ALTER TABLE dbo.example1 ADD
NoNullableCol INT NOT NULL DEFAULT [dbo].SelectMinForeignKey(),
CONSTRAINT FK_example1_DetailTableExample01
FOREIGN KEY (NoNullableCol)
REFERENCES dbo.DetailTableExample01 (ID)
ON UPDATE CASCADE
ON DELETE CASCADE;
AND It`s Done!
Hope it solve your problem