Integrity Constraint Invalid Identifier SQL - sql

I am new to SQL and I am currently have an issue with a constraint I am trying to put on one of my columns.
My database models an art gallery and paintings can either be in the gallery or on loan to another gallery. Obviously it can't be both so I was trying to put a constraint on my on_loan table when creating it to stop the painting ID (P_id) of my on_loan table being the same as the P_id in my in_gallery table. This is what I have done so far:
create table in_gallery (
P_id NUMBER (10) CONSTRAINT PK_IN_GALLERY PRIMARY KEY,
CONSTRAINT IN_GALLERY_FK FOREIGN KEY(P_id) REFERENCES painting(P_id) ON DELETE CASCADE);
create table on_loan (
P_id NUMBER (10),
CONSTRAINT BOOK_IS_IN_GALLERY CHECK(P_id != in_gallery(P_id)));
This comes up with the error:
ERROR at line 3:
ORA-00904: "IN_GALLERY": invalid identifier
How would i fix this error?
Thanks.

You can't reference another table like that in a check constraint.
Check the answers to the question here for some solutions. You could achieve this with a user defined function.
EDIT: Also based on the little bit of information from your post I don't think you have a correct normalized database model. You could have a Gallery table and a Painting table with a relation between the two.

Related

Postgres create table error

I am trying to create my very first table in postgres, but when I execute this SQL:
create table public.automated_group_msg (
automated_group_msg_idx integer NOT NULL DEFAULT nextval ('automated_group_msg_idx'::regclass),
group_idx integer NOT NULL,
template_idx integer NOT NULL,
CONSTRAINT automated_group_msg_pkey PRIMARY KEY (automated_group_msg_idx),
CONSTRAINT automated_group_msg_group_idx_fkey FOREIGN KEY (group_idx)
REFERENCES public.groups (group_idx) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT automated_msg_template_idx_fkey FOREIGN KEY (template_idx)
REFERENCES public.template (template_idx) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
)
WITH (
OIDS = FALSE
);
I get the following error:
ERROR: relation "automated_group_msg_idx" does not exist
Your error is (likely) because the sequence you're trying to use doesn't exist yet.
But you can create a sequence on the fly using this syntax:
create table public.automated_group_msg (
id serial primary key,
... -- other columns
)
Not directly related to your question, but naming columns with the table name in the name of the column is generally speaking an anti-pattern, especially for primary keys for which id is the industry standard. It also allows for app code refactoring using abstract classes whose id column is always id. It's crystal clear what automated_group_msg.id means and also crystal clear that automated_group_msg.automated_group_msg_id is a train wreck and contains redundant information. Attribute column names like customer.birth_date should also not be over-decorated as customer.customer_birth_date for the same reasons.
You just need to create the sequence before creating the table
CREATE SEQUENCE automated_group_msg_idx;

Why can't I add this foreign key?

I'll post only the main part. I have two tables, each one has to have the PK of the other as a FK.
CREATE TABLE apartment
(
cod_apartment INT NOT NULL PRIMARY KEY,
cod_offer INT NOT NULL
);
CREATE TABLE offer
(
cod_offer INT NOT NULL PRIMARY KEY,
cod_apartment INT NOT NULL
);
First I inserted the values on both tables and it was working, I could even search using "select * from...". But then I tried to add the foreign key:
This worked.
ALTER TABLE offer
ADD FOREIGN KEY (cod_apartment ) REFERENCES apartment;
And this not.
ALTER TABLE apartment
ADD FOREIGN KEY (cod_offer) REFERENCES offer;
This is the error message:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK__apartment__cod_offer__6383C8BA". The conflict occurred in database "kleber_apartment", table "dbo.offer", column 'cod_offer'.
The problem is, every time I try to execute, the FK name changes. And this FK actually doesn't exist. I already dropped both tables and tried to insert the values again, but the same happens.
What could be?
That means you're trying to add a foreign key when existing data doesn't obey that constraint. So you have a record in your apartment table where the cod_offer column does not match any value in the cod_apartment table.
Adding a foreign key not only constrains future data, but it requires that any existing data must also follow the rule.
And regarding the 6383C8BA, whenever you add a constraint without giving it a name, SQL Server picks one for you. Personally, I'd recommend something like:
alter table dbo.apartment
add constraint FK_apartment__cod_offer
foreign key (cod_offer) references dbo.offer (cod_offer);
This lets you define names the way you want, and is a little more clear about what you're actually building.

ORA-02264: name already used by an existing constraint [duplicate]

This question already has an answer here:
SQL error: "name already used by an existing constraint"
(1 answer)
Closed 7 years ago.
I Am Working On SQL And I Am Facing A Problem In Creating The Table!
Here Is My Code:
CREATE TABLE Voucher_Types
(
ID Number(3, 0),
Abbreviation VarChar(2),
Voucher_Type VarChar(100),
EntryBy VarChar(25),
EntryDate Date,
CONSTRAINT ID_PK Primary Key(ID)
);
And I Get The Following Error,
ORA-02264: name already used by an existing constraint
I Am Using Oracle10g
I Goggled It And Found Some Topics But They Didn't Help Me, Can Somebody Help Me In This Problem! Thanks In Advance..!
You have another table that has already a constrained with the name ID_PK.
If you want to find out which table it is, you might try
select owner, table_name from dba_constraints where constraint_name = 'ID_PK';
Most probably, you copied your create table statement but did not change the primary key's constraint name.
It is generally felt to be good practice to include the table name in a constraint's name. One reason is exactly to prevent such "errors".
So, in your case, you might use
CREATE TABLE Voucher_Types
(
...
CONSTRAINT Voucher_Types_PK Primary Key(ID)
);
Update Why can't the same constraint name be used twice? (As per your question in the comment): This is exactly because it is a name that identifies the constraint. If you have a violation of a constraint in a running system, you want to know which constraint it was, so you need a name. But if this name can refer multiple constraints, the name is of no particular use.
The error message tells you that there's already another constraint named ID_PK in your schema - just use another name, and you should be fine:
CREATE TABLE Voucher_Types
(
ID Number(3, 0),
Abbreviation VarChar(2),
Voucher_Type VarChar(100),
EntryBy VarChar(25),
EntryDate Date,
CONSTRAINT VOUCHER_TYPES_ID_PK Primary Key(ID)
);
To find the offending constraint:
SELECT * FROM user_constraints WHERE CONSTRAINT_NAME = 'ID_PK'
this means that there is a constraint named ID_PK try with
CONSTRAINT Voucher_Types_ID_PK Primary Key(ID) for instance
you can check whether exists with
select * from user_constraints where upper(constraint_name) = 'ID_PK';
or
select * from all_constraints where upper(constraint_name) = 'ID_PK';
you have same constraint name in other table
you need to change the constraint name
if you want to see table name which you used this constraint
you can see following query:
select table_name,constraint_name from user_constraints where lower(constraint_name)='id_pk';
The anwser of Frank Schmitt is good.
However for the name of your constraint you can also use the table alias as part of your constraint name.
The name of your constraint would be something like: vte_pk. And there is no necessary to invoke the name of the concerning column in the constraint name.
What if the primary key is over 2 (or more) columns?
Thus ... CONSTRAINT VTE_PK Primary Key(ID) ....

Correct way to create a table that references variables from another table

I have these relationships:
User(uid:integer,uname:varchar), key is uid
Recipe(rid:integer,content:text), key is rid
Rating(rid:integer, uid:integer, rating:integer) , key is (uid,rid).
I built the table in the following way:
CREATE TABLE User(
uid INTEGER PRIMARY KEY ,
uname VARCHAR NOT NULL
);
CREATE TABLE Recipes(
rid INTEGER PRIMARY KEY,
content VARCHAR NOT NULL
);
Now for the Rating table: I want it to be impossible to insert a uid\rid that does not exist in User\Recipe.
My question is: which of the following is the correct way to do it? Or please suggest the correct way if none of them are correct. Moreover, I would really appreciate if someone could explain to me what is the difference between the two.
First:
CREATE TABLE Rating(
rid INTEGER,
uid INTEGER,
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid),
FOREIGN KEY (rid) REFERENCES Recipes,
FOREIGN KEY (uid) REFERENCES User
);
Second:
CREATE TABLE Rating(
rid INTEGER REFERENCES Recipes,
uid INTEGER REFERENCES User,
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid)
);
EDIT:
I think User is problematic as a name for a table so ignore the name.
Technically both versions are the same in Postgres. The docs for CREATE TABLE say so quite clearly:
There are two ways to define constraints: table constraints and column constraints. A column constraint is defined as part of a column definition. A table constraint definition is not tied to a particular column, and it can encompass more than one column. Every column constraint can also be written as a table constraint; a column constraint is only a notational convenience for use when the constraint only affects one column.
So when you have to reference a compound key a table constraint is the only way to go.
But for every other case I prefer the shortest and most concise form where I don't need to give names to stuff I'm not really interested in. So my version would be like this:
CREATE TABLE usr(
uid SERIAL PRIMARY KEY ,
uname TEXT NOT NULL
);
CREATE TABLE recipes(
rid SERIAL PRIMARY KEY,
content TEXT NOT NULL
);
CREATE TABLE rating(
rid INTEGER REFERENCES recipes,
uid INTEGER REFERENCES usr,
rating INTEGER NOT NULL CHECK (rating between 0 and 5),
PRIMARY KEY(rid,uid)
);
This is a SQL Server based solution, but the concept applies to most any RDBMS.
Like so:
CREATE TABLE Rating (
rid int NOT NULL,
uid int NOT NULL,
CONSTRAINT PK_Rating PRIMARY KEY (rid, uid)
);
ALTER TABLE Rating ADD CONSTRAINT FK_Rating_Recipies FOREIGN KEY(rid)
REFERENCES Recipies (rid);
ALTER TABLE Rating ADD CONSTRAINT FK_Rating_User FOREIGN KEY(uid)
REFERENCES User (uid);
This ensures that the values inside of Rating are only valid values inside of both the Users table and the Recipes table. Please note, in the Rating table I didn't include the other fields you had, just add those.
Assume in the users table you have 3 users: Joe, Bob and Bill respective ID's 1,2,3. And in the recipes table you had cookies, chicken pot pie, and pumpkin pie respective ID's are 1,2,3. Then inserting into Rating table will only allow for these values, the minute you enter 4 for a RID or a UID SQL throws an error and does not commit the transaction.
Try it yourself, its a good learning experience.
In Postgresql a correct way to implement these tables are:
CREATE SEQUENCE uid_seq;
CREATE SEQUENCE rid_seq;
CREATE TABLE User(
uid INTEGER PRIMARY KEY DEFAULT nextval('uid_seq'),
uname VARCHAR NOT NULL
);
CREATE TABLE Recipes(
rid INTEGER PRIMARY KEY DEFAULT nextval('rid_seq'),
content VARCHAR NOT NULL
);
CREATE TABLE Rating(
rid INTEGER NOT NULL REFERENCES Recipes(rid),
uid INTEGER NOT NULL REFERENCES User(uid),
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid)
);
There is no real difference between the two options that you have written.
A simple (i.e. single-column) foreign key may be declared in-line with the column declaration or not. It's merely a question of style. A third way should be to omit foreign key declarations from the CREATE TABLE entirely and later add them using ALTER TABLE statements; done in a transaction (presumable along with all the other tables, constraints, etc) the table would never exist without its required constraints. Choose whichever you think is easiest fora human coder to read and understand i.e. is easiest to maintain.
EDIT: I overlooked the REFERENCES clause in the second version when I wrote my original answer. The two versions are identical in terms of referential integrity, there are just two ways of syntax to do this.

MySQL Error Code: 1005

I am trying to add foreign keys to my table but receiving this error.
Error Code: 1005 Can't create table 'william.#sql-88c_3' (errno: 150)
I have 3 tables. employee, client and Contract.
employe [employee_no PK] , Client[customer_no PK] contract [contract_no PK]
I want to have Foreign keys for contract as contract [contract_no PK, employee_no FK], customer_no FK]
I tried to do directly it failed, I am now trying the alter statement.Is anything wrong with the Alter script?
ALTER TABLE contract
ADD CONSTRAINT `employee_no_fk2` FOREIGN KEY (`employee_no`) REFERENCES `employee`
(`employee_no`);
ALTER TABLE contract
ADD CONSTRAINT `Customer_no_fk2` FOREIGN KEY (`Customer_no`) REFERENCES `client`
(`Customer_no`);
Most of such error will be related to data type miss match or so.. If you could go through these links.. it might help you i guess.. Check-this
... also Check-this
As they say in the second link:
The first place you should look is whether the data types agree
between the foreign key and primary key columns.
mysql> SHOW engine innodb STATUS;
------------------------
LATEST FOREIGN KEY ERROR
------------------------
100130 17:16:57 Error IN FOREIGN KEY CONSTRAINT OF TABLE sampledb/#sql-4a0_2:
FOREIGN KEY(member_type)
REFERENCES common_lookup(common_lookup_id):
Cannot find an INDEX IN the referenced TABLE WHERE the
referenced COLUMNS appear AS the FIRST COLUMNS, OR COLUMN types
IN the TABLE AND the referenced TABLE do NOT MATCH FOR CONSTRAINT.
make sure that one of the key field that you are trying to reference does not have an index and/or is not a primary key. and the two key fields type and/or size should be an exact match also make sure that both tables are InnoDB tables.
This can happen due to two reasons
Table creation failed because a foreign key constraint was not correctly formed or
Datatype mismatch in the constraints.
the below link would be helpful
http://dev.mysql.com/doc/refman/5.0/en/innodb-error-codes.html
Last time I encountered this, it was the constraints: referenced table key type was 'int' and referring table had 'unsigned int' referring field by mistake, instead of int.