MySQL Stored Procedure, read from one table and insert to other - mysql

I have this following code in PHP and I want to convert this into MySQL stored procedure. I do not want to check on duplication error at db level error code due to the requirement of the application, it has to be done the same way as is done in PHP.
$sql2 = "SELECT zip__ID FROM zip WHERE zip_code='" . $zip . "' ";
$result2 = mysql_query($sql2);
if (mysql_num_rows($result2) == 0) {
$sql3 = "INSERT INTO zips SET zip_code='" . ($zip) . "'";
mysql_query($sql3);
$newZip = mysql_insert_id();
} else {
$row2 = mysql_fetch_array($result2);
$newZip = $row2['zip_id'];
}
//Update: May 6, 2015.
I have total 6 tables.
Table 1 contains fields like zip, city, state, country. This is in varchar format.
|ID|ZIP|CITY|STATE|COUNTRY|
|1|33430|Fort Lauderdale|FL|USA
There are four more tables that are:
Table 2: zips (id,zip_code)
Table 3: cities (id,city_name)
Table 4: state (id,state_name)
Table 5: countries (id,country_name)
I want to insert the date from table 1 into table 6, which is the replica of table 1. The only difference is that in Table 6, I want to insert IDs of the data in table 1. Hence, for every insertion to be made in Table 6, I have to run a query in the 4 tables (2,3,4 and 5). For instance, if the zip code in Table 1 is 33430 and it does not exist in Table 2, first I need to insert it, get its ID and then insert in Table 6.
I have to do the same for all fields in Table 1.
So if I do it in PHP, what I will do it:
$sql = "SELECT * FROM Table1";
$result = mysql_query($sql);
while($row=mysql_fetch_array($result){
$zip = $row['zip'];
$city = $row['city'];
$state = $row['state'];
$country = $row['country'];
//Process zip code
$sql2 = "SELECT zip_id FROM zips WHERE zip_code='" . $zip . "' ";
$result2 = mysql_query($sql2);
if (mysql_num_rows($result2) == 0) {
$sql3 = "INSERT INTO zips SET zip_code='" . ($zip) . "'";
mysql_query($sql3);
$newZip = mysql_insert_id();
} else {
$row2 = mysql_fetch_array($result2);
$newZip = $row2['zip_id'];
}
mysql_free_result($result2);
//Process city
$sql2 = "SELECT city_id FROM cities WHERE city_name='" . $city . "' ";
$result2 = mysql_query($sql2);
if (mysql_num_rows($result2) == 0) {
$sql3 = "INSERT INTO cities SET city_name='" . ($city) . "'";
mysql_query($sql3);
$newCity = mysql_insert_id();
} else {
$row2 = mysql_fetch_array($result2);
$newCity = $row2['city_id'];
}
mysql_free_result($result2);
//process other two tables......
}mysql_free_result($result);

I'm no MySQL expert either, but this is what I could find. You have to check out the syntax though. But I want to stress this. I Googled 2 sources, and I typed this out for you. If I could do it, I'm sure you could've done it as well.
CREATE PROCEDURE UpdateTable6()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE i, a, b, c, d INT;
DECLARE va, vb, vc, vd CHAR(<yourmax>);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE cur1 CURSOR FOR SELECT id, zip, city, state, country FROM table1;
OPEN cur1;
read_loop: LOOP
FETCH cut1 into i, va, vb, vc, vd;
IF done THEN
LEAVE read_loop;
END IF;
--REPEAT THIS FOR ALL 4 TABLES
IF (SELECT 1 = 1 FROM Table2 WHERE zip_code=va) THEN
BEGIN
SELECT a = TableID FROM Table2 WHERE zip_code=va;
END;
ELSE
BEGIN
INSERT INTO Table2 (zip_code) VALUES(va);
SELECT a = LAST_INSERT_ID();
END;
END IF;
--CHECK DETAILS IN TABLE6
IF (SELECT 1 = 1 FROM Table6 WHERE id=i) THEN
BEGIN
UPDATE TABLE6 set zip_id = a, city_id = b, state_id = c, country_id = d where id = i
END;
ELSE
BEGIN
INSERT INTO Table6 (zip_id, city_id, state_id, country_id ) VALUES(a, b, c, d);
END;
END IF;
END LOOP;
CLOSE cur1;
END;
My source where https://dev.mysql.com/doc/refman/5.0/en/cursors.html

Related

Update same tables from from select value from same table mysql

i am trying to update a table column which same column from same table select.
Here is the code (updated)
public function UpdateStockIn($id, $subUnitValue) {
$query = "UPDATE BRAND_LIST SET CURRENT_STOCK_BOTTLE = (SELECT CURRENT_STOCK_BOTTLE FROM BRAND_LIST WHERE ID = ?) + '.$subUnitValue.' WHERE ID = ? ";
$success = 0;
try {
$stmt = $this->conn->prepare($query);
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $id);
$stmt->execute();
$success = 1;
} catch (PDOException $ex) {
echo $ex->getMessage();
}
return $success;
}
it Show error like this
You can't specify target table 'BRAND_LIST' for update in FROM clause
Try run these 2 sqls, The first one will store a value into mysql local variable then use into 2nd sql.
SELECT #old_subUnitValue := GROUP_CONCAT(table1.CURRENT_STOCK_BOTTLE) FROM BRAND_LIST AS table1 WHERE table1.ID=2;
UPDATE BRAND_LIST AS table2 SET table2.CURRENT_STOCK_BOTTLE = #old_subUnitValue + '.$subUnitValue.' WHERE table2.ID=2;
Use the below query
$query = "UPDATE BRAND_LIST SET CURRENT_STOCK_BOTTLE = CURRENT_STOCK_BOTTLE + ".$subUnitValue." WHERE ID = ?";

What is fastest way to update multiple columns in a table from data of another table where updating table column(s) are something?

I have these two queries which work, but they are slow as can be. What is faster, or rather fastest way of doing this?
method 1)
$query = "
UPDATE list_data_extra
INNER JOIN list_data
ON (list_data_extra.serial_no = list_data.serial_no)
SET
list_data_extra.id = list_data.id,
list_data_extra.cid = list_data.cid,
list_data_extra.first = list_data.first,
list_data_extra.last = list_data.last,
list_data_extra.tracking_number = list_data.tracking_number
WHERE list_data_extra.id='0' AND list_data_extra.cid='0'
";
method 2)
$query = "UPDATE list_data_extra
INNER JOIN list_data USING (serial_no)
SET list_data_extra.id = list_data.id,
list_data_extra.cid = list_data.cid,
list_data_extra.first = list_data.first,
list_data_extra.last = list_data.last,
list_data_extra.tracking_number = list_data.tracking_number
WHERE list_data_extra.id='0'
AND list_data_extra.cid='0'";
Not sure this other method would be faster:
method 3)
$query="SELECT * FROM list_data_extra WHERE id='0' AND cid='0'";
$result=mysql_query($query);
$num_rows = mysql_num_rows($result);
if ($num_rows > 0) {
while($row=mysql_fetch_array($result)) {
$querytwo = mysql_fetch_array(mysql_query(
"SELECT id, cid, first, last, tracking_number
FROM list_data
WHERE serial_no='".$row['serial_no']."'"), MYSQL_ASSOC);
$querythree = "UPDATE list_data_extra
SET id='".$querytwo["id"]."', cid='".$querytwo["cid"]."',
first='".$querytwo["first"]."', last='".$querytwo["last"]."',
tracking_number='".$querytwo["tracking_number"]."'";
mysql_query($querythree);
}
}
Another thing i tried is this, which is building entire query then executing it all at once, which is a bit faster than above, but still slow as junk. the above is like 9 minutes per 1000 records and this here below is like 5 minutes per 1000.
method 4)
$query="SELECT * FROM list_data_extra WHERE id='0' AND cid='0'";
$result=mysql_query($query);
$num_rows = mysql_num_rows($result);
if ($num_rows > 0) {
$id_loop = "";
$cid_loop = "";
$first_loop = "";
$last_loop = "";
$trackingnumber_loop = "";
$listids = "";
while($row=mysql_fetch_array($result)) {
$querytwo = mysql_fetch_array(mysql_query("SELECT id, cid, first, last, tracking_number FROM list_data WHERE serial_no='".$row['serial_no']."'"), MYSQL_ASSOC);
$id_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["id"]."' ";
$cid_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["cid"]."' ";
$first_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["first"]."' ";
$last_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["last"]."' ";
$trackingnumber_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["tracking_number"]."' ";
$listids .= ", ".$row['listid'];
}
$listidsb = substr($listids, 2);
$querythree = "UPDATE list_data_extra
SET
id = CASE listid
".$id_loop."
END,
cid = CASE listid
".$cid_loop."
END,
first = CASE listid
".$first_loop."
END,
last = CASE listid
".$last_loop."
END,
tracking_number = CASE listid
".$trackingnumber_loop."
END
WHERE listid IN (".$listidsb.")";
mysql_query($querythree) or die(mysql_error());
}
Is there a better and faster way to update multiple columns in many records in one table with data from another table?
CREATE TABLE list_data (
id int(11) NOT NULL AUTO_INCREMENT,
cid int(11) NOT NULL,
first varchar(255) NOT NULL,
last varchar(255) NOT NULL,
tracking_number varchar(255) NOT NULL,
serial_no varchar(9) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=555555 DEFAULT CHARSET=latin1
Unindexed JOIN and WHERE conditions can be slow, especially if they involve string data; try running these two (they make take a little time to run if the tables are large), and then trying your original query again.
ALTER TABLE list_data
ADD INDEX serial_idx (serial_no);
ALTER TABLE list_data_extra
ADD INDEX serial_idx (serial_no);

MySQL Query with dynamic column name

I have a source table with these columns:
I also have a destination table like this:
The destination table has 1440 rows, with the minute column filled in (1 row for each minute in the day).
For each row in the source table, I need to fill in a "1" in the destination table for the appropriate channel (there are 10 channels total), for every minute between the StartTime and FinishTime.
I'm just doing this in MySQL Workbench (it's a one-time query). What is my beast approach?
Thanks,
-Scott
Pseudo-code:
SELECT DISTINCT ChannelNumber
FROM source
while ($row = fetch_assoc()) {
$channel_col = 'ch'.$row['ChannelNumber']
$sql = "
UPDATE destination
JOIN source ON StartTime = destination.minutes
AND source.ChannelNumber = $row[ChannelNumber]
SET destination.$channel_col = 1
";
query($sql);
}
Normally you have to be concerned about dynamically creating a string which becomes an SQL query to avoid SQL injection, but since all the data is coming from within your database it shouldn't be a problem.
Here is an MySQL solution:
CREATE PROCEDURE PopulateDestinationTable()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE n INT DEFAULT 0;
DECLARE CNumber INT DEFAULT 0;
DECLARE STime INT DEFAULT 0;
DECLARE FTime INT DEFAULT 0;
SELECT COUNT(*) FROM SourceTable INTO n;
SET i = 0;
WHILE i < n DO
SELECT ChanelNumber FROM SourceTable LIMIT i, 1 INTO CNumber;
SELECT StartTime FROM SourceTable LIMIT i, 1 INTO STime;
SELECT FinishTime FROM SourceTable LIMIT i, 1 INTO FTime;
SET #stat1 = CONCAT('UPDATE DestinationTable
SET ', CONCAT('Ch', CNumber), ' = 1 WHERE minutes BETWEEN ? AND ?');
PREPARE statement FROM #stat1;
SET #p1 = STime;
SET #p2 = FTime;
EXECUTE statement USING #p1, #p2;
SET i = i + 1;
END WHILE;
END$$
P.S. Don't forget to change Delimiter when create stored procedure :)
I modified the PHP code from #peter-bowers to this and got it to work:
<?php
$mysqli = new mysqli("ip", "user", "pass", "db");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
echo $mysqli->host_info . "\n";
$res = $mysqli->query("update scott_test set Ch1 = null, Ch2 = null, Ch3 = null, Ch4 = null, Ch5 = null, Ch6 = null, Ch7 = null, Ch8 = null, Ch9 = null, Ch10 = null");
$res = $mysqli->query("SELECT TIMESTAMPDIFF(MINUTE,DATE(TimeReceived),TimeReceived) AS StartTime,
CEIL(FaxDuration/60)+ TIMESTAMPDIFF(MINUTE,DATE(TimeReceived),TimeReceived) AS FinishTime,
ChannelNumber
FROM
fax_received
WHERE
DATE(TimeReceived) = DATE((NOW() - INTERVAL 3 DAY))");
while ($row = $res->fetch_assoc()) {
$channel_col = 'ch'.$row['ChannelNumber'];
$start_min = $row['StartTime'];
$end_min = $row['FinishTime'];
$sql = "UPDATE scott_test
SET $channel_col = 1
WHERE minutes between ($start_min, $end_min);
$mysqli->query($sql);
}
?>

get me the latest Change from Select Query in below given condition

I have a Table structure as
id, trackid, table_name, operation,
oldvalue, newvalue, field,
changedonetime
Now if I have 3 rows for the same "trackid" same "field", then how can i select the latest out of the three?
i.e. for e.g.:
id = 100 trackid = 152 table_name
= jos_menu operation= UPDATE oldvalue = IPL newvalue = IPLcccc
field = name live = 0 changedonetime =
2010-04-30 17:54:39
and
id = 101 trackid = 152 table_name =
jos_menu operation= UPDATE oldvalue
= IPLcccc newvalue = IPL2222 field = name live = 0 changedonetime =
2010-04-30 18:54:39
As u can see above the secind entry is the latest change,
Now what query I should use to get the only one and Latest row out of many such rows...
$distupdqry = "select DISTINCT trackid,table_name from jos_audittrail where live = 0 AND operation = 'UPDATE'";
$disupdsel = mysql_query($distupdqry);
$t_ids = array();
$t_table = array();
while($row3 = mysql_fetch_array($disupdsel))
{
$t_ids[] = $row3['trackid'];
$t_table[] = $row3['table_name'];
//$t_table[] = $row3['table_name'];
}
//echo "<pre>";print_r($t_table);echo "<pre>";
//exit;
for($n=0;$n<count($t_ids);$n++)
{
$qupd = "SELECT * FROM jos_audittrail WHERE operation = 'UPDATE' AND trackid=$t_ids[$n] order by changedone DESC ";
$seletupdaudit = mysql_query($qupd);
$row4 = array();
$audit3 = array();
while($row4 = mysql_fetch_array($seletupdaudit))
{
$audit3[] = $row4;
}
$updatefield = '';
for($j=0;$j<count($audit3);$j++)
{
if($j == 0)
{
if($audit3[$j]['operation'] == "UPDATE")
{
//$insqry .= $audit2[$i]['operation']." ";
//echo "<br>";
$updatefield .= "UPDATE `".$audit3[$j]['table_name']."` SET ";
}
}
if($audit3[$j]['operation'] == "UPDATE")
{
$updatefield .= $audit3[$j]['field']." = '".$audit3[$j]['newvalue']."', ";
}
}
/*echo "<pre>";
print_r($audit3);
exit;*/
$primarykey = "SHOW INDEXES FROM `".$t_table[$n]."` WHERE Key_name = 'PRIMARY'";
$prime = mysql_query($primarykey);
$pkey = mysql_fetch_array($prime);
$updatefield .= "]";
echo $updatefield = str_replace(", ]"," WHERE ".$pkey['Column_name']." = '".$t_ids[$n]."'",$updatefield);
}
In the above code I am fetching ou the distinct IDs in which update operation has been done, and then accordingly query is fired to get all the changes done on different fields of the selected distinct ids...
Here I am creating the Update query by fetching the records from the initially described table which is here mentioned as audittrail table...
Therefore I need the last made change in the field so that only latest change can be selected in the select queries i have used...
please go through the code.. and see how can i make the required change i need finally..
This is another question of the greatest-n-per-group category, which comes up several times per week on Stack Overflow.
Here's how I'd solve it in your case:
SELECT j1.*
FROM jos_audittrail j1 LEFT OUTER JOIN jos_audittrail j2
ON (j1.trackid = j2.trackid AND j1.field = j2.field
AND j1.changedonetime < j2.changedonetime)
WHERE j2.id IS NULL;

if specific row = null, execute query

how do i check if the value of a column is null, and only then execute the query? for example:
col1 col2 col3
01 abc
i run a query which first checks if the record exists or not; if it exists, it should execute the update query and if it doesn't exist, it executes the insert query. how do i check if col3 is null and if it is null, it should execute the update query. .
$sql = "SELECT uid FROM `users` WHERE uid = '" . $user_id . "'";
$result = mysql_query($sql,$conn) or die('Error:' .mysql_error());
$totalrows = mysql_num_rows($result);
if($totalrows < 1)
{
insertUser($user_id,$sk, $conn);
}
else
{
updateSessionKey($user_id,$sk,$conn);
}
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
Not really checking a value of the column, but I don't think you actually need that.
You need to have uid as a UNIQUE column. You try to insert a row for a new user with the given uid; if it finds the user with the same uid, then you do the update instead.
UPDATE:
I guess you did not bother to read the link.
I did not test it, but it should be something like this:
INSERT INTO users (uid, name, session)
VALUES ('login', 'Real Name', 'SeSsIoN_iD')
ON DUPLICATE KEY UPDATE session='SeSsIoN_iD'
This will insert the user if he does not exist, and if he does, it will set a new session key. OR, if you want to preserve the old session key if he already has one,
INSERT INTO users (uid, name, session)
VALUES ('login', 'Real Name', 'SeSsIoN_iD')
ON DUPLICATE KEY UPDATE session=IFNULL(session, 'SeSsIoN_iD')
One query, not three. You were not already doing it.
$sql = "SELECT * FROM `users` WHERE uid = '" . $user_id . "'";
$result = mysql_query($sql,$conn) or die('Error:' .mysql_error());
$totalrows = mysql_num_rows($result);
if($totalrows < 1)
{
$res = mysql_fetch_array($sql);
if(!empty($res['col3'])) {
insertUser($user_id,$sk, $conn);
}
}
else
{
updateSessionKey($user_id,$sk,$conn);
}
Is this what you mean?
If the record does not exist -> insert.
If the record does exist and its col3 is null -> update
If the record does exist, but its col3 is not null -> do nothing?
That could be achieved like this (untested):
$sql = "SELECT uid, col3 FROM `users` WHERE uid = '" . $user_id . "'";
$result = mysql_query($sql,$conn) or die('Error:' .mysql_error());
$totalrows = mysql_num_rows($result);
if($totalrows < 1)
{
insertUser($user_id,$sk, $conn);
}
else
{
$col3value = mysql_result($result, 0, 'col3');
if (is_null($col3value))
{
updateSessionKey($user_id,$sk,$conn);
}
}