Nullify column values of deleted rows - sql

For example, I have these tables and data:
TABLE: logo_user
+----+---------+
| id | logo_id |
+----+---------+
| 1 | 1 |
| 2 | 2 |
+----+---------+
TABLE: logo
+----+
| id |
+----+
| 1 |
| 2 |
+----+
What I want is to delete every rows in logo table, and nullify the values that refers to it. Example:
TABLE: logo_user
+----+---------+
| id | logo_id |
+----+---------+
| 1 | NULL |
| 2 | NULL |
+----+---------+
TABLE: logo (now emptied)
I tried using TRUNCATE ... CASCADE but it also deleted every rows in the logo_user table.
I also consider altering the foreign key constraint of the logo_user to cascade on delete, but it's too much work. In reality I have many tables referring to logo table.

you can use the below solution for your problem.
ON DELETE SET NULL
on a foreign key in your main table will solve the problem in one step. What it basically does is :
if a record in the parent table is deleted, then the corresponding records in the child table will have the foreign key fields set to null (the columns that you would be mentioning in the key). The records in the child table will not be deleted, the corresponding values would be updated to null as per your requirement. For example you can refer to the below syntax :
CREATE TABLE table_name
(
column1 datatype null/not null,
column2 datatype null/not null,
...
CONSTRAINT fk_col
FOREIGN KEY (column1, column2, ... column_n)
REFERENCES parent_table (column1, column2, ... column_n)
ON DELETE SET NULL
);

I don't know why it's "too much work" to modify the foreign keys to ON DELETE SET NULL - it's not just the easiest way, you will have to do it since the default NO ACTION will prevent you from deleting without a cascade.

Related

How can i insert into table on the basis of a column value is same or not in Postgresql

I am inserting data into a table looks like this
| num | name | value |
----------------------------------
| 1 | name1 | 1 |
| 2 | name2 | 1 |
| 3 | name3 | 1 |
| 4 | name4 | 2 |
| 5 | name5 | 3 |
I wanted to insert with where clause like insert into table (num, name, value) values(6,name,1) when (num and value together) not exist in any row together
I tried to select first and insert on basis of that result but I think that is not the best way I want it in a single query
tried like: select * from the table where name=$name and value= $value if I got result then not insert otherwise insert. It was done with two queries but i don't want it.
Any help will be appriciated.
Use a unique constraint to enforce uniqueness for (num, value):
alter table t add constraint unq_t_num_value unique (num, value);
Then the database ensures that the integrity of the table -- that these values are unique. You don't have to do it explicitly.
Note that if the unique constraint is violated, you get an error and the insert is aborted (along with other rows that might be inserted). If you want to ignore the error instead, you can use on conflict ignore.

How to Create table in SQL with table level unique key with table level Identity Seed

I want a table where Column1 and column2 must be unique along with auto Identity on Column1:
Ex:
Create table Foo (Id int, Name varchar(50));
Id column must be auto increment itself.
Data will passed like
A
A
B
B
Data to be inserted like below:
1 A
2 A
1 B
2 B
How can I achieve the same?
When you're using MySQL and can live with having a table with MyISAM engine, there's a built in functionality:
For MyISAM tables, you can specify AUTO_INCREMENT on a secondary
column in a multiple-column index. In this case, the generated value
for the AUTO_INCREMENT column is calculated as
MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is
useful when you want to put data into ordered groups.
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
In this case (when the AUTO_INCREMENT column is part of a
multiple-column index), AUTO_INCREMENT values are reused if you delete
the row with the biggest AUTO_INCREMENT value in any group. This
happens even for MyISAM tables, for which AUTO_INCREMENT values
normally are not reused.
source

SQL Server Conditional Foreign Key

I have two tables in my SQL Server database, Foo and Bar. Table Foo is like so:
+-------+
| Foo |
+-------+
| Id |
| Type |
| Value |
+-------+
The table has values like:
+----+--------+-----------+
| Id | Type | Value |
+----+--------+-----------+
| 1 | Status | New |
| 2 | Status | Old |
| 3 | Type | Car |
| 4 | State | Inventory |
| 5 | State | Sold |
+----+--------+-----------+
The table Bar is like so:
+----------+
| Bar |
+----------+
| Id |
| TypeId |
| StatusId |
| StateId |
+----------+
Where TypeId, StatusId and StateId are all foreign key'ed to the Foo table.
But I want to put a condition on each foreign key where they can only key to the Foo
ids related to it's type. For example, the TypeId column can ONLY foreign key to id
3 on the Foo table. Or the StatusId column can ONLY foreign key to ids 1 or 2.
I know there is a check function in SQL Server but I'm unsure on how to use it correctly. I
tried to do something like this:
CREATE TABLE TEST.dbo.Bar
(
Id int PRIMARY KEY NOT NULL IDENTITY,
TypeId int NOT NULL CHECK (Type='Type'),
CONSTRAINT FK_Bar_Foo_Type FOREIGN KEY (TypeId) REFERENCES Foo (Id, Type)
)
CREATE UNIQUE INDEX Bar_Id_uindex ON TEST.dbo.Bar (Id)
But this didn't work. What am I doing wrong?
The check constraints you are referring to are only used to limit the type of information stored in a key or non key column. So, if you don't want a key column to have a negative value (lets say its a price column, and there is never a negative price) you will use Check constraint.
To better understand the concept of primary and foreign keys:
Primary key uniquely identifies each record in a table.
Foreign key is a value in some table which is a unique identifier (and can also be a primary key) in another table. This means that Foreign key can repeat many times in the table in which it is a foreign key in, and it will definitely be unique in the table that it is created from ( in the table that gives meaning to it).
Now coming to your question, you probably need to use the concept of composite keys. A composite key is basically a group of two or more values that uniquely identify a record, because you cannot enforce limitations on foreign keys in the way you are intending to do, because that defeats the very purpose of a key. Handle some issues with type of data stored in your keys at the application layer instead of database layer.
Looking at the problem in this manner will conceptually resolve some design flaws with your tables as as well.

Can I add a foreign key to already existing table with data?

I am wondering if I can add a foreign key to an already existing table with records in it.
The tables structure and the data in it looks like that at the moment:
Books table:
ID | BookName | BookCode | BookEdition | AuthorID
1 | Name1 | Code1 | 1 | 1
2 | Name1 | Code1 | 2 | 2
Authors table:
ID | AuthorName
1 | Name1
2 | Name2
Basically, I want to add link the two tables based on the AuthorID, the problem is that the column already has data in it, as shown in the example above, but these ids are the correct ones and they also exist in the Authors table.
Is it possible to do that without re-creating the tables?
You can do this using alter table:
alter table books add constraint fk_books_authorid
foreign key (AUthorId) references Authors(ID);

SQL Server Delete - Foreign Key

I have got two tables in SQL Server 2005:
USER Table: information about user and so on.
COUNTRY Table : Holds list of whole countries on the world.
USER_COUNTRY Table: Which matches, which user has visited which county.
It holds, UserID and CountryID.
For example, USER_COUNTRY table looks like this:
+----+--------+-----------+
| ID | UserID | CountryID |
+----+--------+-----------+
| 1 | 1 | 34 |
| 2 | 1 | 5 |
| 3 | 2 | 17 |
| 4 | 2 | 12 |
| 5 | 2 | 21 |
| 6 | 3 | 19 |
+----+--------+-----------+
My question is that: When a user is deleted in USER table, how can I make associated records in USER_COUNTRY table deleted directly. Maybe, by using Foreign Key Constaint?
You have to define a foreign key in USER_COUNTRY that points to USER.UserID and set cascaded deletion:
CREATE TABLE USER_COUNTRY (
...
CONSTRAINT USER_COUNTRY_FK1 FOREIGN KEY (UserID)
REFERENCES USER(UserID)
ON DELETE CASCADE
);
Yes, you could set your foreign key relationship Delete rule to Cascade.
I guess CASCADE is your only option. But do you really want to hard delete records like this? Context: I'm a data fiend.