In MySql we can choose INSERT IGNORE(do not update existing) to generate a sql file with query CREATE TABLE IF NOT EXISTS and INSERT IGNORE INTO.
But in this case,if the table exists, the "INSERT IGNORE INTO" will insert data again.
I'd like to ask,is there a method, to realize the function: If table doesn't exist, it will create the table and insert data.
If the table exists, it will not insert data.
In fact I have tried how to realize, I know with a stored procedure it is possible, but with a sql file which will be executed by batch file, how to realize the function?
My curent code is like this
CREATE DATABASE IF NOT EXISTS martintest;
USE martintest;
CREATE TABLE IF NOT EXISTS `martin1` (
`col1` int(11) default NULL,
`col2` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT IGNORE INTO `martin1` (`col1`, `col2`) VALUES (2, 'bbb'), (1, 'aaa');
One option, perhaps not recommended (one must be careful with session variables, in this case, with: #`table_exists?`), but an option in the end, is something like:
/* CODE FOR DEMONSTRATION PURPOSES */
USE `martintest`;
SET #`table_schema` := 'martintest', #`table_name` := 'martin1';
SELECT EXISTS
(
SELECT NULL
FROM `information_schema`.`TABLES` `ist`
WHERE `ist`.`TABLE_SCHEMA` = #`table_schema` AND `ist`.`TABLE_NAME` = #`table_name`
)
INTO #`table_exists?`;
CREATE TABLE IF NOT EXISTS `martin1` (
`col1` int(11) DEFAULT NULL,
`col2` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `martin1` SELECT 2, 'bbb' FROM DUAL WHERE 0 = #`table_exists?`;
INSERT INTO `martin1` SELECT 1, 'aaa' FROM DUAL WHERE 0 = #`table_exists?`;
/* CODE FOR DEMONSTRATION PURPOSES */
Use CREATE TABLE without IF NOT EXISTS.
If the table exists, it will fail and the rest of the file will not be imported .
Do not use --force parameter,.
Check if the table exists first:
USE martintest;
SET #tablecount := 0
SELECT #tablecount := count(*)
INTO #tablecount
FROM information_schema.tables
WHERE table_schema = 'martintest'
AND table_name = 'martin1'
--check if table count = 0
IF #tablecount = 0
(
CREATE TABLE `martin1` (
`col1` int(11) default NULL,
`col2` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `martin1` (`col1`, `col2`) VALUES (2, 'bbb'), (1, 'aaa');
)
Related
I'm pushing data from a data-frame into MySQL, right now it is only adding new data to the table if the data does not exists(appending). This works perfect, however I also want my code to check if the record already exists then it needs to update. So I need it to append + update. I really don't know how to start fixing this as I got stuck....someone tried this before?
This is my code:
engine = create_engine("mysql+pymysql://{user}:{pw}#localhost/{db}"
.format(user="root",
pw="*****",
db="my_db"))
my_df.to_sql('my_table', con = engine, if_exists = 'append')
You can use next solution on DB side:
First: create table for insert data from Pandas (let call it test):
CREATE TABLE `test` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`capacity` INT(11) NOT NULL,
PRIMARY KEY (`id`)
);
Second: Create table for resulting data (let call it cumulative_test) exactly same structure as test:
CREATE TABLE `cumulative_test` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`capacity` INT(11) NOT NULL,
PRIMARY KEY (`id`)
);
Third: set trigger on each insert into the test table will insert ore update record in the second table like:
DELIMITER $$
CREATE
/*!50017 DEFINER = 'root'#'localhost' */
TRIGGER `before_test_insert` BEFORE INSERT ON `test`
FOR EACH ROW BEGIN
DECLARE _id INT;
SELECT id INTO _id
FROM `cumulative_test` WHERE `cumulative_test`.`name` = new.name;
IF _id IS NOT NULL THEN
UPDATE cumulative_test
SET `cumulative_test`.`capacity` = `cumulative_test`.`capacity` + new.capacity;
ELSE
INSERT INTO `cumulative_test` (`name`, `capacity`)
VALUES (NEW.name, NEW.capacity);
END IF;
END;
$$
DELIMITER ;
So you will already insert values into the test table and get calculated results in the second table. The logic inside the trigger can be matched for your needs.
Similar to the approach used for PostgreSQL here, you can use INSERT … ON DUPLICATE KEY in MySQL:
with engine.begin() as conn:
# step 0.0 - create test environment
conn.execute(sa.text("DROP TABLE IF EXISTS main_table"))
conn.execute(
sa.text(
"CREATE TABLE main_table (id int primary key, txt varchar(50))"
)
)
conn.execute(
sa.text(
"INSERT INTO main_table (id, txt) VALUES (1, 'row 1 old text')"
)
)
# step 0.1 - create DataFrame to UPSERT
df = pd.DataFrame(
[(2, "new row 2 text"), (1, "row 1 new text")], columns=["id", "txt"]
)
# step 1 - create temporary table and upload DataFrame
conn.execute(
sa.text(
"CREATE TEMPORARY TABLE temp_table (id int primary key, txt varchar(50))"
)
)
df.to_sql("temp_table", conn, index=False, if_exists="append")
# step 2 - merge temp_table into main_table
conn.execute(
sa.text(
"""\
INSERT INTO main_table (id, txt)
SELECT id, txt FROM temp_table
ON DUPLICATE KEY UPDATE txt = VALUES(txt)
"""
)
)
# step 3 - confirm results
result = conn.execute(
sa.text("SELECT * FROM main_table ORDER BY id")
).fetchall()
print(result) # [(1, 'row 1 new text'), (2, 'new row 2 text')]
I have a table with auto-incremented ID, colA and colB (with set default value), e.g.:
CREATE TABLE `some_db`.`test` ( `id` INT NOT NULL AUTO_INCREMENT , `colA` INT NOT NULL , `colB` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`)) ENGINE = InnoDB;
Now, I want user to be able to insert the new row, but at the same time DO NOT allow to modify id (auto-incremented) or colB (just use default value).
Is that possible?
I tried to give INSERT and UPDATE only for colA, but that still gives me INSERT command denied error:
GRANT SELECT, INSERT (`colA`), UPDATE (`colA`) ON `some_db`.`test` TO 'test_user'#'%';
I don't know if that matters, I'm using MariaDB.
Thanks!
EDIT:
OK, I need to re-state my question now.
After executing e.g.:
INSERT INTO `test` (`colA`) VALUES (10)
Everything is working fine.
But phpmyadmin GUI (that I use as a front-end here) is translating to:
INSERT INTO `test` (`id`, `colA`, `colB`) VALUES (NULL, 10, ``)
...when no values are given, and it can't be executed (#1143 - INSERT command denied to user test_user#...
So, is there any way that rows can be inserted through phpmyadmin GUI (not SQL command) with such restrictions? (I edited the question title).
CREATE TABLE `test` ( `id` INT NOT NULL AUTO_INCREMENT ,
`colA` INT NOT NULL ,
`colB` INT NOT NULL DEFAULT '0' ,
PRIMARY KEY (`id`)) ENGINE = InnoDB;
CREATE TRIGGER tr_bi_test
BEFORE INSERT
ON test
FOR EACH ROW
SET NEW.id = NULL, NEW.colB = 0;
INSERT INTO test (colA) VALUES (11);
INSERT INTO test (colA, colB) VALUES (22, 222);
INSERT INTO test (id, colA) VALUES (3333, 33);
INSERT INTO test (id, colA, colB) VALUES (4444,44,444);
SELECT * FROM test;
id
colA
colB
1
11
0
2
22
0
3
33
0
4
44
0
db<>fiddle here
You cannot use DEFAULT keyword for assigning the value to NEW.colB - in MariaDB it is treated as NULL while using in a trigger. So you need to hardcode this default value, or you may query it from INFORMATION_SCHEMA.COLUMNS.
I have created two tables which i want to insert similar data in.
CREATE TABLE one(
one_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (one_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE two(
two_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (two_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
every time in run insert.
To do that,i am using transactions
START TRANSACTION;
SET #name = uuid();
INSERT INTO one(one_id,name) VALUES (Null,#name);
INSERT INTO two(two_id, name) VALUES (Null, #name);
COMMIT;
This does not produce new values on new inserts.It however inserts the same data in the field name as i wanted.
How can i make this work?.
I don't see a need to move to transactions in order to do that, just add an before insert trigger to the table .
Something like :
CREATE TRIGGER `ONE_TABLE_TRIGG` BEFORE INSERT ON `one`
FOR EACH
ROW BEGIN
SET NEW.name= UUID( );
END ;
You can check if it's null before doing that. do this on both tables and you're good or add insert to the other table on 1 trigger.
I solved it without much complexities by having several having several transaction statements in the same file
START TRANSACTION;
SET #name = uuid();
INSERT INTO one(one_id,name) VALUES (Null,#name);
INSERT INTO two(two_id, name) VALUES (Null, #name);
COMMIT;
START TRANSACTION;
SET #name = uuid();
INSERT INTO one(one_id,name) VALUES (Null,#name);
INSERT INTO two(two_id, name) VALUES (Null, #name);
COMMIT;
/*
Etc
*/
CREATE TABLE IF NOT EXISTS `MyTable` (
`ID` SMALLINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO MyTable (ID,Name) VALUES (ID=4,Name='xxx')
or
INSERT INTO MyTable (Name) VALUES (Name='xxx')
The problem is that both INSERT statements produce the entry (4,0). Why 0 instead of "xxx"?
UPDATE: Primary key changed.
This should do the job :
INSERT INTO MyTable (ID, Name) VALUES (4, 'xxx')
I'm pretty sure it would be something like this, instead...
INSERT INTO MyTable (Name) VALUES ('xxx')
No need for the Name= part, since you've already specified which column you wish to insert into with the first (Name) definition.
Because the expression Name='xxx' is false, hence evaluates as zero.
You use the column=expression method use in on duplicate key update clauses as described here, not in the "regular" section of inserts. An example of that:
insert into mytable (col1,col2) values (1,2)
on duplicate key update col1 = col1 + 1
You should be using the syntax:
INSERT INTO MyTable (ID,Name) VALUES (4,'xxx')
Is that syntax of Name='xxx' valid? Never seen it before, i assume it is seeing it as an unquoted literal, trying to convert it to a number and coming up with 0? I'm not sure at all
Try this:
INSERT INTO MyTable (Name) VALUES ('xxx')
This is because you should mention the name of the column in the values part. And also because you do not define you primary key correctly (airlineID is not part of the field list)
CREATE TABLE IF NOT EXISTS `MyTable` (
`ID` SMALLINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO MyTable (ID,Name) VALUES (4,'xxx')
INSERT INTO MyTable (Name) VALUES ('xxx')
Try this
INSERT INTO MyTable (ID,Name) VALUES (4,xxx)
For more Info just visit this link
I have a question about the syntax for creating and accessing temporary tables.Here is a
related question.
My table
CREATE TABLE IF NOT EXISTS `table1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`address` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `table1`
--
INSERT INTO `table1` (`id`, `name`, `address`) VALUES
(1, 'andrew', '5 road'),
(2, 'bob', '6 street');
I am running this query.
CREATE TEMPORARY TABLE temptable SELECT id, name, address
FROM table1
SELECT id, name, address
FROM temptable
And tried this one
CREATE TEMPORARY TABLE temptable SELECT id, name, address
FROM table1
DESCRIBE temptable
Creating the temp table works, but then when I try to get info out of the temp table I get a message saying I need to check my sql syntax.
thanks
andrew
I left out the ';' after each statement. My query should have looked like this
CREATE TEMPORARY TABLE temptable SELECT id, name, address
FROM table1;
SELECT id, name, address
FROM temptable;
Details are important in programming and so is stackoverflow