MySQL inserting data only if table doesn't exist - mysql

Using strictly SQL (no PHP or anything else), is it possible to create a table and insert default data into that table only if that table doesn't exist?

Use the CREATE TABLE ... SELECT format:
create table if not exists tablename as
select * from defaultdata;

Here is one way of doing it:
CREATE TABLE IF NOT EXISTS T (
ID int(10) unsigned NOT NULL primary key,
NAME varchar(255) NOT NULL
);
REPLACE INTO T SELECT 1, 'John Doe';
REPLACE INTO T SELECT 2, 'Jane Doe';
REPLACE is a MySQL extension to the SQL standard that either inserts, or deletes and inserts.

You might do a select on the one of the meta data tables
if(not exists select * from whatever_meta where table_name = "whatever)
begin
...
end
You would have to do some research to figure out how exactly...

Can you store the table status as a variable, then use that variable to determine whether to insert data? Ex:
#status = SHOW TABLES LIKE 'my_table';
INSERT INTO my_table VALUES (1,'hello'),(2,'world') WHERE #status <> false;
The problem with Paul Morgan's answer is that it expects data to already exist in another table. Jonas' answer would be extremely resource exhaustive, especially if there's a lot of REPLACES (which are unnecessary if the table exists).

May be I am missing the point but why can't the default data be a set of insert statements...and what one simply needs to do is create the table if it does not exist followed by insert statements...that ways the default data does not have to exist in a different table.

Related

INSERT INTO ... SELECT if destination column has a generated column

Have some tables:
CREATE TABLE `asource` (
`id` int(10) unsigned NOT NULL DEFAULT '0'
);
CREATE TABLE `adestination` (
`id` int(10) unsigned NOT NULL DEFAULT '0',
`generated` tinyint(1) GENERATED ALWAYS AS (id = 2) STORED NOT NULL
);
I copy a row from asource to adestination:
INSERT INTO adestination
SELECT asource.*
FROM asource;
The above generates an error:
Error Code: 1136. Column count doesn't match value count at row 1
Ok, quite strange to require me to mention generated query. But ok, I add that column to the query:
INSERT INTO adestination
SELECT asource.*, NULL AS `generated`
FROM asource;
This has worked fine in 5.7.10. However, it generates an error in 5.7.11 (due to a fix:
Error Code: 3105. The value specified for generated column 'generated' in table 'adestination' is not allowed.
Ok, next try:
INSERT INTO adestination
SELECT asource.*, 1 AS `generated`
FROM asource;
But still the same error. I have tried 0, TRUE, FALSE but the error persists.
The DEFAULT value which is stated as the only allowed value (specs or docs). However, the following generates a syntax error (DEFAULT is not supported there):
INSERT INTO adestination
SELECT asource.*, DEFAULT AS `generated`
FROM asource;
So, how can I copy a row from one table to another using INSERT INTO ... SELECT if the destination table adds some columns where some of them are GENERATED?
The code calling this query is generic and has no knowledge what columns that particular tables have. It just knows which extra columns the destination table has. The source table is a live table, the destination table is a historical version of the source table. It has few columns extra like user id made the change, what type of the change it is (insert, update, delete) when etc.
Sadly this is just how MySQL works now to "conform to SQL standards".
The only value that the generated column can accept in an update, insert, etc. is DEFAULT, or the other option is to omit the column altogether.
My poor mans work around for these are to just disable the generated column while I'm working with the data (like for importing a dump) and then go back and add the generated column expression afterwards.
You must declare the columns
Insert into adestination (id, generated)
select id, 1
from asource;
It is best practice to list out the columns, and use null as field1 for the auto incremented id field.
INSERT INTO adestination
(id,
field1,
field2)
SELECT
null AS generated,
asource.field1,
asource.field2
FROM asource;

Mysql Insert if not exist in two column

I looked into MySQL duplicate key but cant figure it out.
I have a table like below:
id series chapter path(can be unique)
I want only insert data and not update. Lets say I have data like below:
seri:Naruto, klasor:567 ==> If both of these exist in table then do not insert.
seri:Naruto, klasor:568 ==> If Naruto exist but 568 does not exist then do insert.
How can I achieve this?
Easiest way would be to define unique index with two columns on that table:
ALTER TABLE yourtable ADD UNIQUE INDEX (seri,klasor);
You may also define two column primary key, which would work just as well.
Then use INSERT IGNORE to only add rows when they will not be duplicates:
INSERT IGNORE INTO yourtable (seri, klasor) VALUES ('Naruto',567);
INSERT IGNORE INTO yourtable (seri, klasor) VALUES ('Naruto',568);
Edit: As per comments, you can't use UNIQUE INDEX which complicates things.
SET #seri='Naruto';
SET #klasor=567;
INSERT INTO yourtable
SELECT seri,klasor FROM (SELECT #seri AS seri, #klasor AS klasor)
WHERE NOT EXISTS (SELECT seri, klasor FROM yourtable WHERE seri=#seri AND klasor=#klasor);
You may use the above query with two local variables or convert it to single statement by replacing the local variables with actual values.
Better way would be to use stored procedure:
CREATE PROCEDURE yourinsert (vseri VARCHAR(8), vklasor INT)
BEGIN
DECLARE i INT;
SELECT COUNT(*) INTO i FROM yourtable WHERE seri=vseri AND klasor=vklasor;
IF i=0 THEN
INSERT INTO yourtable (seri,klasor) VALUES (vseri, vklasor);
END IF;
END;
This would allow you to perform the INSERT using:
CALL yourinsert('Naruto',567);
INSERT INTO table_name (seri, klasor) VALUES ('Naruto',567)
WHERE NOT EXISTS( SELECT seri,klasor FROM table_name WEHERE seri='Naruto' AND klasor=567
)
Hope this helps..

MySQL Procedure - Insert row if not exists

OK, this is what I want to do :
If an entry already exists (e.g. based on field name), then just return its id
If it doesn't, add it
This is what I've managed so far (for the "if doesn't exist, create it" part) :
INSERT INTO `objects` (`id`,`name`)
SELECT NULL,'someObj2' FROM `objects`
WHERE NOT EXISTS
(SELECT name FROM `objects` WHERE `name`='someObj2');
SELECT LAST_INSERT_ID();
How can I get the id (instead of LAST_INSERT_ID()) if the entry does exist?
P.S. Yep, I know that the main reason I can't get my head around SQL is the degree at which I'm used to the more classical if-then-else approach of regular programming languages... lol
UPDATE :
I keep trying and trying and this what I've managed so far (as a stored procedure) :
IF EXISTS (SELECT * FROM `objects` WHERE `name` = NAME)
THEN
SELECT `id` FROM `objects` WHERE `name` = NAME;
ELSE
INSERT INTO `objects` (`id`,`name`) VALUES(NULL,NAME);
SELECT LAST_INSERT_ID() AS 'id';
END IF
and calling it like: CALL insertObject("someObj2");
However, it's not working as expected - neither does it add the entry, nor does it return the id (instead it returns all ids in the table...). Any idea what could be going wrong?
It looks like you are trying to enforce a unique constraint on name. If so, you can also do this by just declaring the column to be unique or equivalently creating a unique index:
create unique index objects_name on objects(name);
If this is true, then change the question from getting the last inserted id to just getting the id for name:
select id
from objects o
where o.name = 'someObj2';
I hasten to add that in a high-transaction environment where things are being added and deleted quickly, any approach might have a problem. Consider your code, the row could be inserted and then deleted, even before the last_insert_id() is executed. If you are dealing with a high transaction environment with potential race conditions, then you need to use transactions and locking to do what you want.

MySql Basic table creation/handing

I'm trying to create a simple table where I insert field and I do some checks in MySql. I've used Microsoft SQL relatively easy. Instead, MySql give evrrytime query errors without even specifying what's going on. Poor MySql software design apart, here's what I'm trying to do:
1 table with 4 fields with an autoincremental autogenerated number to det an ID as primary key
CREATE TABLE `my_db`.`Patients_table` (
`ID_Patient` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`Patient_name` VARCHAR( 200 ) NOT NULL ,
`Recovery_Date` DATETIME NOT NULL ,
`Recovery_count` INT NOT NULL
) ENGINE = MYISAM
a simple stored procedure to insert such fields and check if something exist before inserting:
CREATE PROCEDURE nameInsert(IN nome, IN data)
INSERT INTO Patients_table (Patient_name,Recovery_Date) values (nome,data)
IF (EXISTS (SELECT Recovery_count FROM Tabella_nomi) = 0) THEN
INSERT INTO (Patients_table (Recovery_count)
ELSE
SET Recovery_count = select Recovery_count+1 from Patients_table
END
this seems wrong on many levels and MySQL useless syntax checker does not help.
How can I do this? Thanks.
There seems to be a lot wrong with this block of code. (No offense intended!)
First, Procedures need to be wrapped with BEGIN and END:
CREATE PROCEDURE nameInsert(IN nome, IN data)
BEGIN
...[actually do stuff here]
END
Second, since your table is declared with all fields as NOT NULL, you must insert all fields with an INSERT statement (this includes the Recovery_Date column, and excludes the AUTO_INCREMENT column). You can add DEFAULT CURRENT_TIMESTAMP to the date column if you want it to be set automatically.
INSERT INTO Patients_table (Patient_name,Recovery_Date) values (nome,data)
Third, what exactly is your IF predicate doing?
EXISTS (SELECT Recovery_count FROM Tabella_nomi) = 0
If you want to check if a row exists, don't put the = 0 at the end. Also, Tabella_nomi isn't declared anywhere in that procedure. Also, your SELECT statement should have a WHERE clause, since I'm assuming you want to select a specific row (this is going to select a result set of all recovery_counts).
Fourth, the second INSERT statement seems a little messy. It should look more like the first INSERT, and keep the point I made above in mind.
INSERT INTO (Patients_table (Recovery_count)
Fifth, the ELSE statement
SET Recovery_count = select Recovery_count+1 from Patients_table
Has some problems too. SET is meant for setting variables, not values in rows. I'm not 100% sure what your intent is from this statement, but it looks like you meant to increment the Recovery_count column of a certain row if it already exists. In which case, you meant to do something like this:
UPDATE Patients_table SET Recovery_count = Recovery_count+1 WHERE <conditional predicate>
Where the conditional predicate is something like this:
Patients_name = nome
Try these things, and look at the errors it gives you when you try to execute the CREATE STATEMENT. I bet they're more useful then you think!

Insert and select the id of a unique element in one query

I have a simple table like this
CREATE TABLE authid(
id INT NOT NULL AUTO_INCREMENT,
authid VARCHAR(128) NOT NULL UNIQUE,
PRIMARY KEY(id)
);
Now if I insert a value with
INSERT INTO authid(authid) VALUES('test');
It will work fine and return the inserted id the first time, but if I do it again when the authid already exists (notice that we have authid marked as UNIQUE) it will return an error.
Is there a way achieve this this in one SQL statement: Insert it, get the id and if it already exists, still get the id.
Take a look at this: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
If you're using MySQL 5.0 or higher you can use the "INSERT ... ON DUPLICATE KEY UPDATE" syntax. You may be able to combine that with LAST_INSERT_ID() (I'm not positive about that)
So:
insert into authid (authid) values ('test') on duplicate key update id=LAST_INSERT_ID(id), authid='test';
select LAST_INSERT_ID();
Well indeed if you try to insert 2 times the same value in a UNIQUE field, it won't work, that's the point of UNIQUE fields.
If I understand well, you want to know if it's possible whether to use an INSERT or an UPDATE statement depending on the existance of an item or not ? Then you need 2 queries, 1 to test existence, the other to insert new value or update existing one
Insert the value conditionally (i.e. if it doesn't exist). Whether the insert takes place or not, by the end of the statement the result will be the same: the value will be in the table. So, just select the ID of the row that matches that value. Or, speaking in SQL, like this:
INSERT INTO authid (authid)
SELECT 'test'
WHERE NOT EXISTS (
SELECT *
FROM authid
WHERE authid = 'test'
);
SELECT id
FROM authid
WHERE authid = 'test'
;