Unique constraint on 2 columns, but in normal and reverse order - sql-server-2008

Couldn't find any answer, so I'm writing this open question. I'm curious if is there any possibility to create such UNIQUE constraint on 2 columns in SQL Server 2008 table, that "normal" and "reverse" duplicates wouldn't be allowed.
Example:
ID1 = 10, ID2 = 20 -- existing row
Trying to add a pair of values:
ID1 = 10, ID2 = 20 -- not allowed because of the UNIQUE key
ID1 = 20, ID2 = 10 -- allowed
The second row will be inserted (of course it's not a duplicate). And that's the issue. Can any key/constraint/whatever be set on a table to disallow above insertion? I.e. something using an expression instead of list of columns? For now I use a trigger which checks for such "duplicates", but I just wonder if is there any simpler solution.
Thanks,
Peter P.

CREATE TABLE dbo.test
(ID1 int , ID2 int ,
CONSTRAINT ID_UK UNIQUE(ID1,ID2),
)
GO
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'check_val' AND type = 'TR')
DROP TRIGGER check_val
GO
CREATE TRIGGER check_val
ON dbo.test
FOR INSERT, UPDATE
AS
if exists ( select i.ID1 ,i.ID2 from inserted i inner join dbo.test t
on t.ID2=i.ID1 and t.ID1=i.ID2 )
RAISERROR ('duplicate values',
16, 1)
ROLLBACK TRANSACTION
GO
insert dbo.test
select 10,20
union
select 20,10

I just needed the exact same thing (just a couple years later)
I decided to go with a check constraint that requires ID1 to be less than ID2
i know that's kinda of hacky, which is why i'm not convinced it's better than the trigger.
now when i insert data, ID1 has to be the smaller else the check constraint fails, that coupled with the unique constraint ensures only one instance of the combination exists.
I'm not anti-trigger, just prefer to not use them unless i really need to
--create your table
create table dbo.test
(
ID1 int not null,
ID2 int not null
)
go
--create a unique constraint the prevents duplicate of id1 and id2
create unique index test_ID1_ID2_uindex
on test (ID1, ID2)
go
--create a check that ensures id1 is less than id2, disallowing something like Id1=20, id2=10
ALTER TABLE dbo.Test
ADD CONSTRAINT CHK_Test_ID1_Less_ID2 CHECK (ID1<ID2);
GO
--this will fail
insert dbo.test
select 10,20
union
select 20,10

Related

MySQL - How to insert or update from source table to target table with different Keys?

I have 2 tables with different structures.
CREATE TABLE test1
(
id INTEGER PRIMARY KEY,
EmpName VARCHAR(50),
Empid INTEGER
);
CREATE TABLE test2
(
Empid INTEGER PRIMARY KEY,
EmpFName VARCHAR(50),
EmpLName VARCHAR(50)
);
Is there a way to insert rows from test2 table into test1? If the row exists in test1 it should update the row as well. I think it's possible with Merge statement but it's not available for MySQL. Is there a similar function like this in MySQL?
I've looked into INSERT ... ON DUPLICATE KEY UPDATE but the tables should have the same primary keys.
I think this can help you.
Create Trigger to detect when insert/update data in your table test2.
Inside Trigger use REPLACE INTO to change data in your table test1.
Please check this link for additional of REPLACE INTO command.
Is there a way to insert rows from test2 table into test1? If the row exists in test1 it should update the row as well
UPDATE test1
JOIN test2 USING (Empid)
SET test1.EmpName = CONCAT_WS(' ', EmpFName, EmpLName)
Pay attention - EmpName max length is 50 whereas total length of combined name may be up to 50+1+50=101, so the combined value may be truncated. Increase max length for EmpName.
If you need to perform this operation automatically when the data in test2 is inserted/updated then use AFTER INSERT and AFTER UPDATE triggers, like
CREATE TRIGGER tr
AFTER INSERT -- and the same trigger on AFTER UPDATE event
ON test2
FOR EACH ROW
UPDATE test1
SET EmpName = CONCAT_WS(' ', NEW.EmpFName, NEW.EmpLName)
WHERE test1.Empid = NEW.Empid;

SQL normalized data INSERT WHERE NOT EXISTS ; ON DUPLICATE KEY UPDATE

i am using MySql Workbench version 6.3.9 with mySql 5.6.35.
i have the following tables:
EQUIPMENT
eID | caochID | eName
COACH
coachID | coachName
SQLfiddle prepared http://sqlfiddle.com/#!9/e333d/1
eID is a primary key. there are multiple coachID's in different equipment, so there will be duplicate coachIDs with different equipment, but the eID will be unique as it is a primary key.
REQUIRED
i need to insert a row in the equipment table, if it does not already exist. If it exists, do nothing.
various posts online have pointed me towards two options:
a) INSERT...ON DUPLICATE KEY UPDATE...
b)INSERT...WHERE NOT EXISTS
PROBLEM i have problems with both of these solutions. for the first solution (ON DUPLICATE KEY UPDATE) the query inserts the row as required but does not update the existing row. instead it creates a new entry. for the second solution (WHERE NOT EXISTS) i get an error : SYNTAX ERROR: 'WHERE' (WHERE) is not a valid input at this position.
the sql query doesnt need to make any joins. i listed both tables so that you can see how they are related. the insert query i need will only insert for the equipment table.
You can insert by using a tmp table and ensuring that the same record is not existing from current table. Add limit 1 to ensure only one record is inserted. Below query will not insert since 1 and small ball exists.
INSERT INTO `Equipment` (`c_id`, `eName`)
SELECT * FROM (SELECT '1', 'small ball') tmp
WHERE NOT EXISTS (
SELECT c_id FROM Equipment WHERE `c_id`='1' and `eName` = 'small ball'
) LIMIT 1;
NOT EXISTS
insert into table2 (....) --- all if not columns ... destination
select ....
from table1 t1 --- source of data to check
where not exists (
select 1
from table2 t2
where t2.col = t1.col --- match source and destination table making sure table1 data is not in table2
)

How to insert if not exists with selecting from same table?

I have my table schema in H2 db as follows:
create table if not exists Test ( id bigint not null,name varchar(255), primary key (id) );
alter table Test add constraint if not exists Test_NAME UNIQUE (name);
I want to insert a value for the name attribute as 'Default' if it does not exist in the table by selecting the latest id value from the table and increment it by one.
Example:
Do not insert if an entry for name = Default already exists.
ID | Name
1 | Default
Insert if an entry for name = Default does not exists.
ID | Name
1 | ABC
2 | XYZ
For the id column, find the max id and increment it by one. In this case, insert id=3 and name=Default.
My query is as follows:
INSERT INTO Test (id , name)
SELECT max(id) + 1, 'Default' from Test
WHERE NOT EXISTS (SELECT * FROM Test where name='Default');
However, it gives me an error saying:
NULL not allowed for column "ID"; SQL statement
as it applies the where condition on the inner select statement.
I also tried:
MERGE INTO Test KEY(name) VALUES (SELECT MAX(id) + 1 from Test, 'Default');
It gives an error because, merge tries to update with the new values.
If it finds 'Default', it will update the row with new id causing primary key violation.
Is there a better way to do this? How can I make the query work?
You are massively overcomplicating this. Define the id field as auto increment and place a unique index on the name field. The unique index prevents duplicate names to be inserted, while the auto increment increases the value of the id field by 1 (by default) if the insert is successful.
I updated id to auto increment and the following query work flawlessly
INSERT INTO Test (name) select * from (select 'Default') as tmp WHERE NOT EXISTS (SELECT name from Test where name='Default');
when you run your query first time, no record found in table so, it give error 'null' there, so if you add IFNULL() function there as below
INSERT INTO Test (id , name)
SELECT **IFNULL**(max(id),0) + 1, 'Default'
FROM Test
WHERE NOT EXISTS (SELECT * FROM Test where name='Default');

Mysql table multiple primary key relation

I have table with 2 columns. ID1 and ID2.
I want make 2 columns as primary key.
When insert ID1=22 , ID2=55 and ID1=55 , ID2=22 this as same and do not insert and show error!
Note*: This table is a relation ship. Same bro and sis. Really have 3 colmuns: ID1 , ID2 , TYP.
ID1 = first user id
ID2 = second user id
TYP = type of relation ship(bro/sis/uncle/aunt...)
Now how can i set all columns as primary? When ID1 and ID2 as how i explain above and also make TYP primary too? Thanks#>
MySQL does not have an easy way of identifying that (id1, id2) and (id2, id1) should be the same.
So, you would need to create a trigger to handle this. If (id1, id2) is already a primary or unique key, then something like this:
delimiter $$
create trigger tr_table_insert before insert on t
for each row
begin
if (exists (select 1
from t
where t.id2 = new.id1 and t.id1 = new.id2
)
) then
set msg = concat('Combination ', new.id1, ' and ', new.id2, ' already exists);
signal sqlstate '45000' set message_text = msg;
end if;
end;
delimiter $$;
You can have primary keys with multiple columns like in this or in this example.
Simply add PRIMARY KEY (ID1, ID2) to your create table statement.
What I'm a bit worried about is that you say (22/55) and (55/22) should be detected as duplicates. With PK on ID1 and ID2 alone that would not be the case. (22/55) and (55/22) are different, but that's perfectly OK with a table for relationships: If 22 is the aunt of 55, then 55 is the nephew of 22, so there should be two rows in that table.

insert if not exists else just select in mysql

I have one mysql table 'alfa' that will contain the primary key of another table 'beta' in one column. But if the entry in 'beta' can not be found I want to insert the value in 'beta' and use the new key in 'alfa'. Can I do this in one query somehow ?
I currently have:
INSERT INTO alfa SET c1=(SELECT id FROM beta WHERE name = 'john');
which works fine when 'john' exists in the table, but fails otherwise. So could I improve it to let the new name be inserted and selected if it is not already there ? id is auto_incremented.
I have tried to looking at IF but have not yet found out how to use IF outside the SELECT, is that possible ?
I know I can do it in several queries but I am talking with a remote database so could be nice to do it all at once.
For example the tables could have been created like this:
CREATE TABLE alfa (
c1 int,
PRIMARY KEY (c1)
)
CREATE TABLE beta (
id int auto_increment,
name varchar(255),
PRIMARY KEY (id)
)
so alfa.c1 should refer to the beta.id values.
In short I want to do:
insert the id for john from the beta table into c1 in alfa, if john does not exist in beta then insert john into beta and insert the new auto incremented id for john into c1 in alfa.
I'll have a go, but bear in mind that coming from a Microsoft SQL background, and I'm not familiar with the exact structure of your tables, so some of the the SQL is probably a bit ropey.
IF (SELECT COUNT(*) FROM beta WHERE name = 'John' > 0)
UPDATE alfa SET c1=(SELECT id FROM beta WHERE name = 'John')
ELSE
BEGIN
INSERT INTO beta (name) VALUES ('John')
INSERT INTO alfa (c1) VALUES (LAST_INSERT_ID())
END
Hope this is of some help.