Insert if pair doesn't exist - mysql

If I have table with 4 columns: rowId | userOneId | userTwoId | timestamp
Is it possible to check whether a pair of users exist and update timestamp if it does? And if it doesn't exist insert new row?
Example of table with expected results:
rowId | userOneId | userTwoId | timestamp
1 a b <timestamp>
2 a c <timestamp>
Now if I want to insert into userOneId a and to userTwoId b, it will update the timestamp. Also possible is if userOneId is b and userTwoId is b update row 1 timestamp as well (would love to see both options - i.e for exact pairs, and for reverse pairs)

THIS ANSWERS THE ORIGINAL VERSION OF THE QUESTION.
I think you want insert . . . on duplicate key update:
insert into t(useroneid, usertwoid, timestamp)
values ($userondid, $usertwoid, $timestamp)
on duplicate key update timestamp = values(timestamp);
In order for this to work, you need a unique index on (useroneid, usertwoid):
create unique index unq_t_useroneid_usertwoid on t(useroneid, usertwoid);

Related

Insert into mysql table only if those values are not in table

I have search already an answer but i can't find one that is good for my situation.
I have a table called Names like this
ID NAME Age
1 Paula 20
2 Mark 17
And i want to run this sql
Insert into table names(name,age) values ("Chriss",15)//should be inserted
Insert into table names(name,age) values ("Mark",17)// should be ignored
Insert into table names(name,age) values ("Andrea",20) //should be inserted
So how can I ignore second insert query
Create a constraint that demands NAME and Age to be unique in the table.
ALTER TABLE `tablename` ADD UNIQUE `unique_index`(`NAME`, `Age`);
You would either need to Add UNIQUE constraint or check the data at the run time (if you don't have a permission to change table schema):
ALTER TABLE `Table_name`
ADD UNIQUE INDEX (`NAME`, `AGE`);
You can use:
INSERT INTO names(name,age)
SELECT * FROM (SELECT 'Chriss', 15) AS tmp
WHERE NOT EXISTS (
SELECT name FROM names WHERE name = 'Chriss' AND age = 15
) LIMIT 1;
An other way is just make the columns name and age UNIQUE so the query fails.
Change your query to this:
Insert into table names(name,age)
SELECT "Chriss",15 WHERE NOT EXISTS (SELECT 1 FROM names WHERE `name` = "Chriss");
Insert into table names(name,age)
SELECT "Mark",17 WHERE NOT EXISTS (SELECT 1 FROM names WHERE `name` = "Mark");
Insert into table names(name,age)
SELECT "Andrea",20 WHERE NOT EXISTS (SELECT 1 FROM names WHERE `name` = "Andrea");
First create a unique constraint for the columns NAME and Age:
ALTER TABLE names ADD UNIQUE un_name_age (`NAME`, `Age`);
and then use INSERT IGNORE to insert the rows:
Insert ignore into names(name,age) values
("Chriss",15),
("Mark",17),
("Andrea",20);
So if you try to insert a duplicate name the error will just be ignored and the statement will continue with the next row to insert.
See the demo.
Result:
| ID | NAME | Age |
| --- | ------ | --- |
| 1 | Paula | 20 |
| 2 | Mark | 17 |
| 3 | Chriss | 15 |
| 4 | Andrea | 20 |

How to generate a unique id based on different id category?

I have a table as shown below
| id | name | doc_no |
|:-----------|------------:|:------------:|
| 1 | abc | D11710001
| 2 | efg | D21710001
| 3 | hij | D31710001
| 4 | klm | D41710001
| 5 | nop | D51710001
| 1 | qrs | D11710002
I want to generate an unique id based on the id given. For example, when i have item to be stored in this table, it will generate an unique id based on the id of the table.
Note: The id in this table is a foreign key. The doc no can be modified by user into their own format manually.
The id format - D 'id' 'year' 'month' 0001(auto increment)
How can i write the sql to generate unique id during storing data?
Continuing with the comment by #strawberry I might recommend not storing the ID in your database. Besides the fact that accessing the auto increment ID at the same time you are inserting the record might be tricky, storing this generated ID would be duplicating the information already stored elsewhere in your table. Instead of storing your ID, just generate it when you query, e.g.
SELECT
id, name, doc_no,
CONCAT('D', id, STR_TO_DATE(date, '%Y-%m'), auto_id) AS unique_id
FROM yourTable;
This assumes that you would be storing the insertion date of each record in a date column called date. It also assumes that your table has an auto increment column called auto_id. Note that having the date of insertion stored may be useful to you in other ways, e.g. if you want to search for data in your table based on date or time.
You could create Trigger and update the column or you can write the update state just after your INSERT
insert into <YOUR_TABLE>(NAME,DOC_NO) values('hello','dummy');
update <YOUR_TABLE> set DOC_NO=CONCAT('D',
CAST(YEAR(NOW()) AS CHAR(4)),
CAST(MONTH(NOW()) AS CHAR(4)),
LAST_INSERT_ID())
WHERE id=LAST_INSERT_ID();
Please note, as above SQL may cause race condition, when simultaneously server get multiple requests.
#Tim Biegeleisen has good point though, as it is better to construct the id when you are SELECTing the data.

in MySQL table, force a value in a record to be one of few options, affected by different value in the same record

I'll make it clearer..I have a table 'cameras' with the following structure:
camera(int) | day_of_week(int) | course_id(int) | open_time(TIME)| close_time(TIME)
and the second table 'students_courses' with the current following structure:
student_id(int) | course_id(int)
now, student_id and course_id are FOREIGN KEY's referenced to 'students' and 'courses' tables , and i want to add two column's to 'students_courses' - open_time and close_time, but the catch is open_time has to be a value existing in 'cameras' with the relevant course_id, and close time has to be a result of the open_time so for example:
if there is this two records in 'cameras' :
`10132 (camera)| 1(day) | 123(course_id) | 14:00:00(open_time) | 16:00:00(close_time)
10442 (camera)| 1(day) | 123(course_id) | 18:00:00(open_time) | 19:30:00(close_time)
and i want to insert new record to 'students_courses' with the course_id = "123" than 'open_time' can only be one of the two => '14:00:00' OR '18:00:00' and if i choose '14:00:00' than 'close_time' can only be '16:00:00', obviously if 'open_time' is 18:00:00 than 'close_time' can only be '19:30:00'...
how am i implementing this logic?...thx
FOREIGN KEY (course_id,open_time,close_time) REFERENCES cameras (course_id, open_time, close_time)
Although I'm not sure why you don't just want to FK to a primary key on cameras ...

Inserting a foreign key, on missing key, update

I have two tables:
tbl1:
============================
ID | TOKEN(indexed)
============================
1 | 2176
2 | 2872
3 | 2881
4 | 1182
tbl2:
=======================
ID | TOKEN_REF
=======================
1 | 2
2 | 3
3 | 1
4 | 1
in each iteration the server would receive a 'token', and would update tbl1 if no token exists, in this example token "5241" would require an insert into tbl1.
I need to update tbl2 where tbl2.ID is AUTO_INCREMENTed whenever a token is received (existing or not).
If the token is a new one, first update tbl1, and only then update tbl2 with the id of the new token.
I was thinking on the INSERT ON EXIST UPDATE, but I don't know how to combine it into a single command.
To summarize:
I need to INSERT ON EXIST UPDATE tbl1 in each iteration and INSERT the resulting ID into tbl2 in a single command. is that possible?
ideas?
I have prepared an SQLFiddle of as per Ondřej's suggestion, which may be found here.
In the schema I have proposed the following After Insert trigger:
CREATE TRIGGER tbl1_ai AFTER INSERT ON tbl1
FOR EACH ROW
INSERT INTO tbl2(TOKEN_REF)
VALUES(new.ID);

Mysql auto_increment proceed with lowest value

My problem is: I have a table with an auto_increment column. When I insert some values, all is right.
Insert first row : ID 1
Insert second row : ID 2
Now I want to insert a row at ID 10.
My problem is, that after this there are only rows inserted after ID 10 (which is the normal behaviour ).
But I want that the database first fills up ID 3-9 before making that.
Any suggestions?
EDIT:
To clarify: this is for an URL shortener I want to build for myself.
I convert the id to a word(a-zA-z0-9) for searching, and for saving in the database I convert it to a number which is the ID of the table.
The Problem is now:
I shorten the first link (without a name) -> ID is 1 and the automatically name is 1 converted to a-zA-Z0-9 which is a
Next the same happenes -> ID is 2 and the name is b, which is 2 converted.
Next interesting, somebody want to name the link test -> ID is 4597691 which is the converted test
Now if somebody adds another link with no name -> ID is 4597692 which would be tesu because the number is converted.
I want that new rows will be automatically inserted at the last gap that was made (here 3)
You could have another integer column for URL IDs.
Your process then might look like this:
If a default name is generated for a link, then you simply insert a new row, fill the URL ID column with the auto-increment value, then convert the result to the corresponding name.
If a custom name is specified for a URL, then, after inserting a row, the URL ID column would be filled with the number obtained from converting the chosen name to an integer.
And so on. When looking up for integer IDs, you would then use the URL ID column, not the table auto-increment column.
If I'm missing something, please let me know.
You could do 6 dummy inserts and delete/update them later as you need. The concept of the auto increment, by design, is meant to limit the application's or user's control over the number to ensure a unique value for every single record entered into the table.
ALTER TABLE MY_TABLE AUTO_INCREMENT = 3;
You would have to find first unused id, store it as user variable, use as id for insert.
SELECT #id := t1.id +1
FROM sometable t1 LEFT JOIN sometable t2
ON t2.id = t1.id +1 WHERE t2.id IS NULL LIMIT 1;
INSERT INTO sometable(id, col1, col2, ... ) VALUES(#id, 'aaa', 'bbb', ... );
You will have to run both queries for every insert if you still have gaps, its up to you to decide whether it is worth doing it.
not 100% sure what you're trying to achieve but something like this might work:
drop table if exists foo;
create table foo
(
id int unsigned not null auto_increment primary key,
row_id tinyint unsigned unique not null default 0
)
engine=innodb;
insert into foo (row_id) values (1),(2),(10),(3),(7),(5);
select * from foo order by row_id;
+----+--------+
| id | row_id |
+----+--------+
| 1 | 1 |
| 2 | 2 |
| 4 | 3 |
| 6 | 5 |
| 5 | 7 |
| 3 | 10 |
+----+--------+
6 rows in set (0.00 sec)