I need to set up some initial records in our mysql database.
I insert a new record which gives me the siteID of the last insert I then use this in creating the rows in my allNews_copy table. The following works (syntax is from applicationcraft ide) as I get the correct structure but there is a 60 timeout for the call to the server.
Therefore the script stops after about 270 rows.
for(i3=1; i3<51; i3++) {
//console.log('i3 = '+i3 );
for(i2=1; i2<101; i2++) {
//console.log('i2 = '+i2 );
var isVisible2 = 0;
if(i2 < 6){ isVisible2 = 1;}
cObj.insert('allNews_copy',{
siteID:siteID,
newsIDInt:i2,
catIDInt:i3,
title:'Item title '+i2 + ' in Cat' + i3,
newsDesc:'Item Desc',
visible:isVisible2
});
}
}
The total number of rows would be 5000.
So can I do this by using a mysql loop via a std mysql syntax?
In standard SQL syntax you can insert multiple rows in a single statement:
INSERT INTO table (<list of columns>)
VALUES (<list of values>), (<list of values>), (<list of values>), ...
I don't know how to translate this syntax to the API you're using, though.
Related
I am using Node.js. I use mysql and bluebird packages.
const pool = mysql.createPool({ ... });
const query = (stmt, params) => {
return Promise.promisify(pool.query, { context: pool })(stmt, params);
};
const params = { ... };
const stmt = 'insert into table set ? on duplicate key update ?';
return query(stmt, [params, params])
.then(results => {
// I want to know actually what is done, insert or update
});
There should be a key affectedRows from the return object. From the reference, affectedRows will be 1 if it is inserted, and 0 or 2 if it is updated.
return query(stmt, [params, params])
.then(results => {
// I want to know actually what is done, insert or update
if (results.affectedRows === 1) {
// inserted
} else {
// updated
}
});
For INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values. If you specify the CLIENT_FOUND_ROWS flag, the affected-rows value is 1 (not 0) if an existing row is set to its current values.
Reference: https://dev.mysql.com/doc/refman/8.0/en/mysql-affected-rows.html
While I'm not as savvy with this bit of node api, the basics are the same:
query(stmt, [params.col1, params.col2])
.then(results => {
Console.log("Affected rows: " + results.affectedRows);
});
Now, the real problem is that MySQL is a fan of essentially returning garbage diagnostic information. If you modify more than 1 row, you'll have no idea what occurred on each one, thanks to this:
With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values.
If you can afford it, do these statements one at a time, and check the affected row count. Otherwise, I'm digging through some MySQL internal functions but I'm not seeing much.
As a side note, you're overreaching with your wildcards there. Instead, use that space to update/insert the columns you want, and parameterize the input values:
-- Please don't name it 'table'
INSERT INTO my_table (column1, column2)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE column1 = VALUES(column1), column2 = VALUES(column2)
I have a small DB where i insert new data to each column at a different time. Because I'm only inserting one new value, the values for other columns will become NULL. But if thats the case, i want to keep the old value.
My DB looks like this:
One solution would be using coalesce() i guess, but i'm updating each column dynamically, and so the other column names are unknown.
function database_call(request) {
database.query(request, function (err, result) {
if (err) {
console.log(err);
}
});
}
subscribedItem.on("changed", function (dataValue) {
let databaseAttribute = subscribedItem.itemToMonitor.nodeId.value;
let databaseValue = dataValue.value.value;
databaseAttribute = databaseAttribute.substring(databaseAttribute.indexOf('.')+1)
databaseAttribute = databaseAttribute.replace(".", '');
databaseAttribute = databaseAttribute.replace(/"/g, '');
database_call("INSERT INTO Prozessdaten ("+databaseAttribute+") VALUES ("+databaseValue+")");
});
I've found this that implements a 'vertical' coalesce.
You should first do a query like this, using SUBSTRING_INDEX and GROUP_CONCAT to obtain the latest not-null value available in the database for each column.
SELECT
SUBSTRING_INDEX(GROUP_CONCAT(05Hz ORDER BY ID DESC SEPARATOR '##INDEX##'), '##INDEX##', 1) AS 05Hz,
SUBSTRING_INDEX(GROUP_CONCAT(5Hz ORDER BY updated_at DESC SEPARATOR '##INDEX##'), '##INDEX##', 1) AS 5Hz
FROM
table
LIMIT 1
After that, update the single value you really need to update and perform an insert specifying all the values for every column.
I'm currently using PHP and MySQL to retrieve a set of 100,000 records in a table, then iterate over each of those records to do some calculations and then insert the result into another table. I'm wondering if I'd be able to do this in pure SQL and make the query run faster.
Here's what I"m currently using:
$stmt= $pdo->query("
SELECT Well_Permit_Num
, Gas_Quantity
, Gas_Production_Days
FROM DEP_OG_Production_Import
ORDER
BY id ASC
");
foreach ($stmt as $row) {
$data = array('well_id' => $row['Well_Permit_Num'],
'gas_quantity' => $row['Gas_Quantity'],
'gas_days' => $row['Gas_Production_Days'],
'gas_average' => ($row['Gas_Production_Days']);
$updateTot = $pdo->prepare("INSERT INTO DEP_OG_TOTALS
(Well_Permit_Num,
Total_Gas,
Total_Gas_Days,
Total_Gas_Avg)
VALUES (:well_id,
:gas_quantity,
:gas_days,
:gas_average)
ON DUPLICATE KEY UPDATE
Total_Gas = Total_Gas + VALUES(Total_Gas),
Total_Gas_Days = Total_Gas_Days + VALUES(Total_Gas_Days),
Total_Gas_Avg =(Total_Gas + VALUES(Total_Gas)) / (Total_Gas_Days + VALUES(Total_Gas_Days))");
}
I'd like to see if this can be done in pure MySQL instead of having to use PHP just for the fact of using it to hold the variables.
My Result should be 1 record that is a running total for each Well. The source table may house 60-70 records for the same well, but over a few thousand different Wells.
It's a constant import process that has to be run, so it's not like there is a final table which you can just do SUM(Gas_Quantity)... etc.. on
As commented by Uueerdo, you seem to need an INSERT ... SELECT query. The role of such query is to INSERT insert the resultset returned by an inner SELECT. The inner select is an aggregate query that computes the total sum of gas and days for each well.
INSERT INTO DEP_OG_TOTALS (Well_Permit_Num, Total_Gas, Total_Gas_Days, Total_Gas_Avg)
SELECT
t.Well_Permit_Num,
SUM(t.Gas_Quantity) Total_Gas,
SUM(t.Gas_Production_Days) Total_Gas_Days
FROM DEP_OG_Production_Import t
GROUP BY t.Well_Permit_Num
ON DUPLICATE KEY UPDATE
Total_Gas = Total_Gas + t.Total_Gas,
Total_Gas_Days = Total_Gas_Days + t.Total_Gas_Days,
Total_Gas_Avg =(Total_Gas + t.Total_Gas) / (Total_Gas_Days + t.Total_Gas_Days)
What i'm trying is validate a select query is processed successfully.
With DB transaction we can validate INSERT , UPDATE, DELETE
like shown below in Codeigniter
$this->db->trans_begin();
//query
if($this->db->trans_status() == false){
return ['error' => 1, 'message' => 'Error massage'];
}
but it does not work with SELECT query.
Is there any other ways to validate this.
Actually my select query will be like this in a scenario
SELECT (amount1+ 10 / 100) FROM test_table
the formula (amount1+ 10 / 100) in the above query will be decoded from the user input. some time a wrong input from user can be like this.
(amount1+ + 10 / 100)
so at the time select query will not execute.
#sintakonte the user input that i mentioned is a formula from a formula builder.
so finally i did a simple trick to validate the query (formula).
do an insertion or update to the table with the select query.
In my scenario once i get the result from the select query i have to update
a column in a table.
$this->db->trans_begin();
$this->db->query("UPDATE table2
JOIN (
SELECT (amount1+ 10 / 100) AS amnt, empID FROM test_table
) AS calculationTB
ON calculationTB.empID = table2.empID AND
SET fnTB.ssoEmployer=calculationTB.amnt");
if($this->db->trans_status() == false){
return ['error' => 1, 'message' => 'Error massage'];
}
$this->db->trans_commit();
Check this example before reading the question - http://www.sqlfiddle.com/#!2/fcf3e/8
The following data comes from a form, the user simply removed a product from a special offer.
Array(
'special_offer_id' => 1,
'product_ids' => Array(
0 => 1,
0 => 2
)
)
Originally I wanted to use this query...
REPLACE INTO `foo` VALUES (1, 1), (2, 1);
But this won't remove the product that the user removed - only update the others.
So I'm forced to perform 2 queries...
DELETE FROM `foo` WHERE `special_offer_id` = 1;
INSERT INTO `foo` VALUES (1, 1), (2, 1);
Is there a better way to do this without having to perform 2 queries?
Example: http://www.sqlfiddle.com/#!2/fcf3e/8
I don't think it is possible within MySQL to combine DML statements. I do know that Oracle and MSSQL have the merge function for this but I think MySQL doens't have this function but i'm not quite sure about that.
Looking at your fiddle and what the code actually does I've came up with a different approach. If you loop through your array of data which is present and put the output into 1 variable and use the delete to delete the rows which do not match.
Here's an example based on your sqlfiddle (note that the array is not valid as it is not named correctly in the fiddle)
// Declare var and fill with array result
$exists = '';
for ($c = 0; $c < count($array); c++)
{
if ($c == (count($array) -1))
{
$exists .= $array[$c]['product_ids'];
}
else
{
$exists .= $array[$c]['product_ids'].',';
}
}
Then instead of doing two queries, you can do it with one
DELETE FROM `foo` WHERE `special_offer_id` NOT IN ('.$exists.');