Related
I am attempting to do a bulk insert into MySQL using
INSERT INTO TABLE (a, b, c) VALUES (?, ?, ?), (?, ?, ?)
I have the general log on, and see that this works splendidly for most cases. However, when the table has a BLOB column, it doesn't work as well.
I am trying to insert 20 records.
Without the BLOB, I see all 20 records in the same query in the general log, 20 records inserted in the same query.
WITH the BLOB, I see only 2 records per query in the general log, it takes 10 queries in total.
Is this a problem with MySQL, the JDBC Driver, or am I missing something else. I would prefer to use a BLOB as I have data in protobufs.
Here is an example table...
CREATE TABLE my_table (
id CHAR(36) NOT NULL,
name VARCHAR(256) NOT NULL,
data BLOB NOT NULL,
PRIMARY KEY (id)
);
Then, create your batch inserts in code...
val ps = conn.prepareStatement(
"INSERT INTO my_table(id, name, data) VALUES (?, ?, ?)")
records.grouped(1000).foreach { group =>
group.foreach { r =>
ps.setString(1, UUID.randomUUID.toString)
ps.setString(2, r.name)
ps.setBlob(3, new MariaDbBlob(r.data))
ps.addBatch()
}
ps.executeBatch()
}
If you run this and inspect the general log, you will see...
"2018-10-12T18:37:55.714825Z 4 Query INSERT INTO my_table(id, name, fqdn, data) VALUES ('b4955537-2450-48c4-9953-e27f3a0fc583', '17-apply-test', _binary '
17-apply-test\"AAAA(?2Pending8?????,J$b4955537-2450-48c4-9953-e27f3a0fc583
1:2:3:4:5:6:7:8Rsystem'), ('480e470c-6d85-4bbc-b718-21d9e80ac7f7', '18-apply-test', _binary '
18-apply-test\"AAAA(?2Pending8?????,J$480e470c-6d85-4bbc-b718-21d9e80ac7f7
1:2:3:4:5:6:7:8Rsystem')
2018-10-12T18:37:55.715489Z 4 Query INSERT INTO my_table(id, name, data) VALUES ('7571a651-0e0b-4e78-bff0-1394070735ce', '19-apply-test', _binary '
19-apply-test\"AAAA(?2Pending8?????,J$7571a651-0e0b-4e78-bff0-1394070735ce
1:2:3:4:5:6:7:8Rsystem'), ('f77ebe28-73d2-4f6b-8fd5-284f0ec2c3f0', '20-apply-test', _binary '
20-apply-test\"AAAA(?2Pending8?????,J$f77ebe28-73d2-4f6b-8fd5-284f0ec2c3f0
As you can see, each INSERT INTO only has 2 records in it.
Now, if you remove the data field from the schema and insert and re-run, you will see the following output (for 10 records)...
"2018-10-12T19:04:24.406567Z 4 Query INSERT INTO my_table(id, name) VALUES ('d323d21e-25ac-40d4-8cff-7ad12f83b8c0', '1-apply-test'), ('f20e37f2-35a4-41e9-8458-de405a44f4d9', '2-apply-test'), ('498f4e96-4bf1-4d69-a6cb-f0e61575ebb4', '3-apply-test'), ('8bf7925d-8f01-494f-8f9f-c5b8c742beae', '4-apply-test'), ('5ea663e7-d9bc-4c9f-a9a2-edbedf3e5415', '5-apply-test'), ('48f535c8-44e6-4f10-9af9-1562081538e5', '6-apply-test'), ('fbf2661f-3a23-4317-ab1f-96978b39fffe', '7-apply-test'), ('3d781e25-3f30-48fd-b22b-91f0db8ba401', '8-apply-test'), ('55ffa950-c941-44dc-a233-ebecfd4413cf', '9-apply-test'), ('6edc6e25-6e70-42b9-8473-6ab68d065d44', '10-apply-test')"
All 10 records are in the same query
I tinkered until I found the fix...
val ps = conn.prepareStatement(
"INSERT INTO my_table(id, name, data) VALUES (?, ?, ?)")
records.grouped(1000).foreach { group =>
group.foreach { r =>
ps.setString(1, UUID.randomUUID.toString)
ps.setString(2, r.name)
//ps.setBlob(3, new MariaDbBlob(r.data))
ps.setBytes(r.data)
ps.addBatch()
}
ps.executeBatch()
Using PreparedStatement.setBytes instead of using MariaDbBlob seemed to do the trick
I'm trying to upsert a database table with loopback. The raw query is
insert into all_inventory (sku, qty, regal, fach, skuRegalFach)
values (?, 1, ?, ?, ?)
on duplicate key update
qty = qty + 1,
regal = values(regal),
fach = values(fach)
Is there any way to do this with loopback?
Currently I'm facing two problems.
I get:
ER_DUP_ENTRY: Duplicate entry '22323' for key
'all_inventory_SkuRegalFach_uindex'
Because loopback doesn't seem to be able to handle the key correctly.
And I have no idea how to tell loopback to add 1 to the qty field instead of just overriding it with the new value.
I have it working with a raw query right now,
let ds = Inventory.dataSource,
values = [sku, regal, fach, sku + regal + fach],
sql = `insert into all_inventory (sku, qty, regal, fach, skuRegalFach) values (?, 1, ?, ?, ?) on duplicate key update qty = qty + 1, regal = values(regal), fach = values(fach)`
ds.connector.query(sql, values, (err, products) => {
if (err) return console.error(err);
cb(null, products);
});
Is there a way to do this with loopback's ORM?
I'd use a find filter. Either findById or find with an appropriate filter.
If you get a result, then it exists. You can modify qty and then store it. If it doesn't exist, then you just create it.
I am trying to save multiple queries into a database on two different tables. Below is the code that I have tried to no avail. firsttable.a is the same as secondtable.id, con holds the connection info, and everything saves perfectly with one query. Is there something I am missing here?
if(empty($id)){
$uuid = uniqid();
$query = "INSERT INTO firsttable (`id`, `a`, `b`, `uuid`) VALUES (NULL, '$a', '$b', '$uuid')";
$query2 = "INSERT INTO secondtable (`id`, `c`, `d`, `uuid`) VALUES (NULL, '$c', '$d', '$uuid')";
}else{
$query = "UPDATE `firsttable` SET `id` = '$id', `a` = '$a', `b` = '$b', `uuid` = '$uuid' WHERE `id` = $id";
$query2 = "Update INTO secondtable SET `id` = '$a', `c` = '$c', `d` = '$d',
if(!mysqli_multi_query($this->_con, $query;$query2)){
throw new Exception( mysqli_error($this->_con) );
mysql_multi_query takes two arguments: the database connection, and a single string.
You need to concatenate your two queries together as a string:
mysqli_multi_query($this->con, $query1 . ';' . $query2);
or what you were probably trying to do:
mysqli_multi_query($this->con, "$query1;$query2");
From the php documentation on how to retrieve the result sets for the subsequent queries:
To retrieve the resultset from the first query you can use mysqli_use_result() or mysqli_store_result(). All subsequent query results can be processed using mysqli_more_results() and mysqli_next_result().
The first example shows how it all works.
In your example, though, the correct syntax is UPDATE tablename ..., not UPDATE INTO tablename ....
I have table - config.
Schema:
config_name | config_value
And I would like to update multiple records in one query. I try like that:
UPDATE config
SET t1.config_value = 'value'
, t2.config_value = 'value2'
WHERE t1.config_name = 'name1'
AND t2.config_name = 'name2';
but that query is wrong :(
Can you help me?
Try either multi-table update syntax
UPDATE config t1 JOIN config t2
ON t1.config_name = 'name1' AND t2.config_name = 'name2'
SET t1.config_value = 'value',
t2.config_value = 'value2';
Here is a SQLFiddle demo
or conditional update
UPDATE config
SET config_value = CASE config_name
WHEN 'name1' THEN 'value'
WHEN 'name2' THEN 'value2'
ELSE config_value
END
WHERE config_name IN('name1', 'name2');
Here is a SQLFiddle demo
You can accomplish it with INSERT as below:
INSERT INTO mytable (id, a, b, c)
VALUES (1, 'a1', 'b1', 'c1'),
(2, 'a2', 'b2', 'c2'),
(3, 'a3', 'b3', 'c3'),
(4, 'a4', 'b4', 'c4'),
(5, 'a5', 'b5', 'c5'),
(6, 'a6', 'b6', 'c6')
ON DUPLICATE KEY UPDATE id=VALUES(id),
a=VALUES(a),
b=VALUES(b),
c=VALUES(c);
This insert new values into table, but if primary key is duplicated (already inserted into table) that values you specify would be updated and same record would not be inserted second time.
in my case I have to update the records which are more than 1000, for this instead of hitting the update query each time I preferred this,
UPDATE mst_users
SET base_id = CASE user_id
WHEN 78 THEN 999
WHEN 77 THEN 88
ELSE base_id END WHERE user_id IN(78, 77)
78,77 are the user Ids and for those user id I need to update the base_id 999 and 88 respectively.This works for me.
instead of this
UPDATE staff SET salary = 1200 WHERE name = 'Bob';
UPDATE staff SET salary = 1200 WHERE name = 'Jane';
UPDATE staff SET salary = 1200 WHERE name = 'Frank';
UPDATE staff SET salary = 1200 WHERE name = 'Susan';
UPDATE staff SET salary = 1200 WHERE name = 'John';
you can use
UPDATE staff SET salary = 1200 WHERE name IN ('Bob', 'Frank', 'John');
maybe for someone it will be useful
for Postgresql 9.5 works as a charm
INSERT INTO tabelname(id, col2, col3, col4)
VALUES
(1, 1, 1, 'text for col4'),
(DEFAULT,1,4,'another text for col4')
ON CONFLICT (id) DO UPDATE SET
col2 = EXCLUDED.col2,
col3 = EXCLUDED.col3,
col4 = EXCLUDED.col4
this SQL updates existing record and inserts if new one (2 in 1)
Camille's solution worked. Turned it into a basic PHP function, which writes up the SQL statement. Hope this helps someone else.
function _bulk_sql_update_query($table, $array)
{
/*
* Example:
INSERT INTO mytable (id, a, b, c)
VALUES (1, 'a1', 'b1', 'c1'),
(2, 'a2', 'b2', 'c2'),
(3, 'a3', 'b3', 'c3'),
(4, 'a4', 'b4', 'c4'),
(5, 'a5', 'b5', 'c5'),
(6, 'a6', 'b6', 'c6')
ON DUPLICATE KEY UPDATE id=VALUES(id),
a=VALUES(a),
b=VALUES(b),
c=VALUES(c);
*/
$sql = "";
$columns = array_keys($array[0]);
$columns_as_string = implode(', ', $columns);
$sql .= "
INSERT INTO $table
(" . $columns_as_string . ")
VALUES ";
$len = count($array);
foreach ($array as $index => $values) {
$sql .= '("';
$sql .= implode('", "', $array[$index]) . "\"";
$sql .= ')';
$sql .= ($index == $len - 1) ? "" : ", \n";
}
$sql .= "\nON DUPLICATE KEY UPDATE \n";
$len = count($columns);
foreach ($columns as $index => $column) {
$sql .= "$column=VALUES($column)";
$sql .= ($index == $len - 1) ? "" : ", \n";
}
$sql .= ";";
return $sql;
}
Execute the code below to update n number of rows, where Parent ID is the id you want to get the data from and Child ids are the ids u need to be updated so it's just u need to add the parent id and child ids to update all the rows u need using a small script.
UPDATE [Table]
SET column1 = (SELECT column1 FROM Table WHERE IDColumn = [PArent ID]),
column2 = (SELECT column2 FROM Table WHERE IDColumn = [PArent ID]),
column3 = (SELECT column3 FROM Table WHERE IDColumn = [PArent ID]),
column4 = (SELECT column4 FROM Table WHERE IDColumn = [PArent ID]),
WHERE IDColumn IN ([List of child Ids])
Execute the below code if you want to update all record in all columns:
update config set column1='value',column2='value'...columnN='value';
and if you want to update all columns of a particular row then execute below code:
update config set column1='value',column2='value'...columnN='value' where column1='value'
Assuming you have the list of values to update in an Excel spreadsheet with config_value in column A1 and config_name in B1 you can easily write up the query there using an Excel formula like
=CONCAT("UPDATE config SET config_value = ","'",A1,"'", " WHERE config_name = ","'",B1,"'")
INSERT INTO tablename
(name, salary)
VALUES
('Bob', 1125),
('Jane', 1200),
('Frank', 1100),
('Susan', 1175),
('John', 1150)
ON DUPLICATE KEY UPDATE salary = VALUES(salary);
UPDATE 2021 / MySql v8.0.20 and later
The most upvoted answer advises to use the VALUES function which is now DEPRECATED for the ON DUPLICATE KEY UPDATE syntax. With v8.0.20 you get a deprecation warning with the VALUES function:
INSERT INTO chart (id, flag)
VALUES (1, 'FLAG_1'),(2, 'FLAG_2')
ON DUPLICATE KEY UPDATE id = VALUES(id), flag = VALUES(flag);
[HY000][1287] 'VALUES function' is deprecated and will be removed in a future release. Please use an alias (INSERT INTO ... VALUES (...) AS alias) and replace VALUES(col) in the ON DUPLICATE KEY UPDATE clause with alias.col instead
Use the new alias syntax instead:
official MySQL worklog
Docs
INSERT INTO chart (id, flag)
VALUES (1, 'FLAG_1'),(2, 'FLAG_2') AS aliased
ON DUPLICATE KEY UPDATE flag=aliased.flag;
just make a transaction statement, with multiple update statement and commit. In error case, you can just rollback modification handle by starting transaction.
START TRANSACTION;
/*Multiple update statement*/
COMMIT;
(This syntax is for MySQL, for PostgreSQL, replace 'START TRANSACTION' by 'BEGIN')
Try either multi-table update syntax
Try it copy and SQL query:
CREATE TABLE #temp (id int, name varchar(50))
CREATE TABLE #temp2 (id int, name varchar(50))
INSERT INTO #temp (id, name)
VALUES (1,'abc'), (2,'xyz'), (3,'mno'), (4,'abc')
INSERT INTO #temp2 (id, name)
VALUES (2,'def'), (1,'mno1')
SELECT * FROM #temp
SELECT * FROM #temp2
UPDATE t
SET name = CASE WHEN t.id = t1.id THEN t1.name ELSE t.name END
FROM #temp t
INNER JOIN #temp2 t1 on t.id = t1.id
select * from #temp
select * from #temp2
drop table #temp
drop table #temp2
UPDATE table name SET field name = 'value' WHERE table name.primary key
If you need to update several rows at a time, the alternative is prepared statement:
database complies a query pattern you provide the first time, keep the compiled result for current connection (depends on implementation).
then you updates all the rows, by sending shortened label of the prepared function with different parameters in SQL syntax, instead of sending entire UPDATE statement several times for several updates
the database parse the shortened label of the prepared function , which is linked to the pre-compiled result, then perform the updates.
next time when you perform row updates, the database may still use the pre-compiled result and quickly complete the operations (so the first step above can be omitted since it may take time to compile).
Here is PostgreSQL example of prepare statement, many of SQL databases (e.g. MariaDB,MySQL, Oracle) also support it.
I have a MySQL question that I think must be quite easy. I need to return the LAST INSERTED ID from table1 when I run the following MySql query:
INSERT INTO table1 (title,userid) VALUES ('test',1);
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(),4,1);
SELECT LAST_INSERT_ID();
As you can understand the current code will just return the LAST INSERT ID of table2 instead of table1, how can I get the id from table1 even if I insert into table2 between?
You could store the last insert id in a variable :
INSERT INTO table1 (title,userid) VALUES ('test', 1);
SET #last_id_in_table1 = LAST_INSERT_ID();
INSERT INTO table2 (parentid,otherid,userid) VALUES (#last_id_in_table1, 4, 1);
Or get the max id from table1 (EDIT: Warning. See note in comments from Rob Starling about possible errors from race conditions when using the max id)
INSERT INTO table1 (title,userid) VALUES ('test', 1);
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(), 4, 1);
SELECT MAX(id) FROM table1;
(Warning: as Rob Starling points out in the comments)
Since you actually stored the previous LAST_INSERT_ID() into the second table, you can get it from there:
INSERT INTO table1 (title,userid) VALUES ('test',1);
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(),4,1);
SELECT parentid FROM table2 WHERE id = LAST_INSERT_ID();
This enables you to insert a row into 2 different tables and creates a reference to both tables too.
START TRANSACTION;
INSERT INTO accounttable(account_username)
VALUES('AnAccountName');
INSERT INTO profiletable(profile_account_id)
VALUES ((SELECT account_id FROM accounttable WHERE account_username='AnAccountName'));
SET #profile_id = LAST_INSERT_ID();
UPDATE accounttable SET `account_profile_id` = #profile_id;
COMMIT;
I had the same problem in bash and i'm doing something like this:
mysql -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');"
which works fine:-) But
mysql -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');set #last_insert_id = LAST_INSERT_ID();"
mysql -D "dbname" -e "insert into table2 (id_tab1) values (#last_insert_id);"
don't work. Because after the first command, the shell will be logged out from mysql and logged in again for the second command, and then the variable #last_insert_id isn't set anymore.
My solution is:
lastinsertid=$(mysql -B -N -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');select LAST_INSERT_ID();")
mysql -D "dbname" -e "insert into table2 (id_tab1) values (${lastinsertid});"
Maybe someone is searching for a solution an bash :-)
We only have one person entering records, so I execute the following query immediately following the insert:
$result = $conn->query("SELECT * FROM corex ORDER BY id DESC LIMIT 1");
while ($row = $result->fetch_assoc()) {
$id = $row['id'];
}
This retrieves the last id from the database.
It would be possible to save the last_id_in_table1 variable into a php variable to use it later?
With this last_id I need to attach some records in another table with this last_id, so I need:
1) Do an INSERT and get the last_id_in_table1
INSERT into Table1(name) values ("AAA");
SET #last_id_in_table1 = LAST_INSERT_ID();
2) For any indeterminated rows in another table, UPDATING these rows with the last_id_insert generated in the insert.
$element = array(some ids)
foreach ($element as $e){
UPDATE Table2 SET column1 = #last_id_in_table1 WHERE id = $e
}
Instead of this LAST_INSERT_ID()
try to use this one
mysqli_insert_id(connection)
For no InnoDB solution: you can use a procedure
don't forgot to set the delimiter for storing the procedure with ;
CREATE PROCEDURE myproc(OUT id INT, IN otherid INT, IN title VARCHAR(255))
BEGIN
LOCK TABLES `table1` WRITE;
INSERT INTO `table1` ( `title` ) VALUES ( #title );
SET #id = LAST_INSERT_ID();
UNLOCK TABLES;
INSERT INTO `table2` ( `parentid`, `otherid`, `userid` ) VALUES (#id, #otherid, 1);
END
And you can use it...
SET #myid;
CALL myproc( #myid, 1, "my title" );
SELECT #myid;
In trigger BEFORE_INSERT this working for me:
SET #Last_Insrt_Id = (SELECT(AUTO_INCREMENT /*-1*/) /*as Last_Insert_Id*/
FROM information_schema.tables
WHERE table_name = 'tblTableName' AND table_schema = 'schSchemaName');
Or in simple select:
SELECT(AUTO_INCREMENT /*-1*/) as Last_Insert_Id
FROM information_schema.tables
WHERE table_name = 'tblTableName' AND table_schema = 'schSchemaName');
If you want, remove the comment /*-1*/ and test in other cases.
For multiple use, I can write a function. It's easy.
For last and second last:
INSERT INTO `t_parent_user`(`u_id`, `p_id`) VALUES ((SELECT MAX(u_id-1) FROM user) ,(SELECT MAX(u_id) FROM user ) );
We could also use $conn->insert_id;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com')";
if ($conn->query($sql) === TRUE) {
$last_id = $conn->insert_id;
echo "New record created successfully. Last inserted ID is: " . $last_id;
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
My code does not work for me. Any idea to recover the id of my last insert this is my code I am new developing and I do not know much
I GOT ERROR IN THE QUERY AND I DON'T KNOW HOW TO SEND PRINT IN THE LINE OF $ session-> msg ('s', "Product added successfully. Make cost configuration". LAST_INSERT_ID ());
ALREADY VERIFY AND IT IS CORRECT THE CONNECTION AND THE FIELDS OF THE DATABASE.
<?php
if(isset($_POST['add_producto'])){
$req_fields = array( 'nombre', 'categoria', 'proveedor');
validate_fields($req_fields);
if(empty($errors)){
$codigobarras = remove_junk($db->escape($_POST['codigobarras']));
$identificador = remove_junk($db->escape($_POST['identificador']));
$nombre = remove_junk($db->escape($_POST['nombre']));
$categoria = (int)$db->escape($_POST['categoria']);
$etiquetas = remove_junk($db->escape($_POST['etiquetas']));
$unidadmedida = remove_junk($db->escape($_POST['unidadmedida']));
$proveedor = remove_junk($db->escape($_POST['proveedor']));
$fabricante = remove_junk($db->escape($_POST['idfabricante']));
$maximo = remove_junk($db->escape($_POST['maximo']));
$minimo = remove_junk($db->escape($_POST['minimo']));
$descripcion = remove_junk($db->escape($_POST['descripcion']));
$dias_vencimiento = remove_junk($db->escape($_POST['dias_vencimiento']));
$servicio = "0";
if (isset($_POST['servicio'])){
$servicio =implode($_POST['servicio']);
}
$numeroserie = "0";
if (isset($_POST['numeroserie'])){
$numeroserie =implode($_POST['numeroserie']);
}
$ingrediente = "0";
if (isset($_POST['ingrediente'])){
$ingrediente =implode($_POST['ingrediente']);
}
$date = make_date();
$query = "INSERT INTO productos (";
$query .=" codigo_barras,identificador_producto,nombre,idcategoria,idetiquetas,unidad_medida,idproveedor,idfabricante,max_productos,min_productos,descripcion,dias_vencimiento,servicio,numero_serie,ingrediente,activo";
$query .=") VALUES (";
$query .=" '{$codigobarras}', '{$identificador}', '{$nombre}', '{$categoria}', '{$etiquetas}', '{$unidadmedida}', '{$proveedor}', '{$fabricante}', '{$maximo}', '{$minimo}', '{$descripcion}', '{$dias_vencimiento}', '{$servicio}', '{$numeroserie}', '{$ingrediente}', '1'";
$query .=");";
$query .="SELECT LAST_INSERT_ID();";
if($db->query($query)){
$session->msg('s',"Producto agregado exitosamente. Realizar configuracion de costos" . LAST_INSERT_ID());
redirect('precio_producto.php', false);
} else {
$session->msg('d',' Lo siento, registro falló.');
redirect('informacion_producto.php', false);
}
} else{
$session->msg("d", $errors);
redirect('informacion_producto.php',false);
}
}
?>
Just to add for Rodrigo post, instead of LAST_INSERT_ID() in query you can use SELECT MAX(id) FROM table1;, but you must use (),
INSERT INTO table1 (title,userid) VALUES ('test', 1)
INSERT INTO table2 (parentid,otherid,userid) VALUES ( (SELECT MAX(id) FROM table1), 4, 1)
If you need to have from mysql, after your query, the last auto-incremental id without another query, put in your code:
mysql_insert_id();