I have used bulk update to sync datas between two tables as below
$sqlProc="
UPDATE cards
SET cards.card_no = t2.card_number,
cards.expiry_date=t2.expiry_date OUTPUT INSERTED.Id AS 'updated_id'
FROM cards
INNER JOIN card_temp t2 ON (cards.account_no = t2.account_number
AND cards.customer_name=t2.customer_name)
WHERE cards.is_disabled='N'";
debug($this->Request->query($sqlProc));
Above query will also return Primary key of updated records usingOUTPUT INSERTED.Id AS 'updated_id' in sql server editor but when i debug the sql
debug($this->Request->query($sqlProc));
Then it return true for successful query and false for unsuccessful query.
Is there any idea to fetch updated_id to array , so that i can use those ids to another table
Well , I figured out finally . I created one intermediate table did the following
//inserted into temp_id (bridge table)
$sqlProc="insert into temp_id select * FROM (update cards
set cards.card_no = t2.card_number,cards.expiry_date=t2.expiry_date
OUTPUT INSERTED.Id AS 'updated_id'
from cards
inner join card_temp t2
on (cards.account_no = t2.account_number and cards.customer_name=t2.customer_name)
where cards.is_disabled='N'
) AS t";
$this->Request->query($sqlProc);
//fetch from intermediate table
$sqlSel="SELECT * FROM temp_id";
$arr=$this->Request->query($sqlSel);
//this array will fetch all updated id's
debug($arr);
$sqlDel="DELETE FROM temp_id";
$this->Request->query($sqlDel);
Related
I have two tables, tableA and tableB. They are connected by a foreign key on their IDs (ATableID, BTableID).
TableB has a stored procedure that allows rows to be archived, It has 2 columns in it named Available_Days and Available_Night. In TableA
There is also columns Available_Days and Available_Night, which are joined to tableB by a left join. If there is data in those columns in TableA, you must not be able to archive the row in TableB.
This is the stored procedure currently, I need help implementing the criteria explained above.
#BTableID VARCHAR(500) = '',
#UserArchived INT = 0
AS
DECLARE #Local BTableID VARCHAR(500)
DECLARE #LocalUserArchived INT
DECLARE #LocalSql NVARCHAR(500)
set #Local BTableID = #BTableID;
set #LocalUserArchived = #UserArchived;
set #LocalSql = 'UPDATE tableB
SET DateArchived = GETDATE(),
UserArchived = '+CAST(#UserArchived as NVARCHAR)+'
WHERE BTableID IN ('+# BTableID +')'
I am also open for any suggestions if the current direction isn't wise.
For full context, this stored procedure will be used in php Laravel framework where a user will be able to delete a row(TableB), unless that rows information is referenced elsewhere(TableA), in which case, they will be prompted to update the other table before attempting to delete again.
Once again, the desired result is to prevent archiving/soft deleting (preventing setting DateArchived = GETDATE()) a row if its information is referenced in another table.
UPDATE:
I've made two possible adjustments (currently unable to test them as I'm not able to access the db at the moment.)
set #LocalSql = 'UPDATE BTable
SET DateArchived = GETDATE(),
UserArchived = '+CAST(#UserArchived as NVARCHAR)+'
WHERE BTableID IN ('+#BTableID+')
WHERE NOT EXISTS (
SELECT FROM ATable at
WHERE tp.ATable_FK = tp.BTableID)'
and
set #LocalSql = 'UPDATE tableB
SET DateArchived = GETDATE(),
UserArchived = '+CAST(#UserArchived as NVARCHAR)+'
WHERE tableBID IN ('+#tableBID+')
LEFT JOIN tableA cm ON cm.tableAID = tp.tableBID
WHERE cm.tableAID IS NULL’
I'm not able to test them at this time but will update this post to let you know if either did the job. If you have any suggestions on improvements please leave a comment or answer. :)
SOLUTION:
I figured out a very simple solution to solve my issue. I forgot all about the archive/soft delete stored procedures and created two stored procedures for table A and table B which selects one record from the table. ie :
#TableAIB int
AS
SELECT
TableBID,
TableBDescription,
FROM TableB
WHERE TableBID = #TableBID
RETURN ##ERRO
and
GO
#TableAID int
AS
SELECT
TableAID,
TabelADescritption
FROM TableA
WHERE TableAID = #TableAID
RETURN ##ERROR
GO
these two two tables are connected via a foreign key(on tableAID and tableBID).
in the controller I then did this:
public function archive(int $id)
{
$tableA = tableA::find($id);
$tableB = tableB::find($id);
if ($tableA->TableAID == $tableB->TableBID){
return redirect()->route(‘myPage.index')
->with('warning', ’This can not be archived, it is being used in another row. ');
}
}
This is essentially saying that if the two stored procedure's ID's match, redirect to the index page with a warning.
I need to port some data from tables on a development database into identical tables on the production database, but the production already has records with primary keys that match the dev database so I can't dump the data in with primary keysbundleRenderer.renderToStream
In this case, item_id is the primary key in the parent record, which is used to relate child records to it. Doing the insert of parent records will create a new primary key, so I need child inserts to also have the newly created primary key so that the relationship is maintained on the production databasebundleRenderer.renderToStream
my script so far:
<?php
$DB2connPROD = odbc_connect("schema","user", "pass");
$DB2connDEV = odbc_connect("schema","user", "pass");
//Get itemt records from dev
$getDevitems = "
select item_id,item_typet_id,item_identifier,expiration_timestamp
from development.itemt where item_typet_id in (2,3)
";
//$getDevitems will get records that have a primary key item_id which is used to get the records in the following select queries
foreach($getDevitems as $items){
//Get all comments
$getComments = "
select tc.item_id, tc.comment, tc.comment_type_id from development.item_commentt tc
inner join development.itemt t on tc.item_id = t.item_id
where t.item_id = {item_id_from_getDevitems}
";
$insertitem = "INSERT into production (item_identifier,expiration_timestamp)
values (item_identifier,expiration_timestamp)";
$insertComment = "INSERT into productionComment (item_id, comment, comment_type_id)
values (item_id, comment, comment_type_id)";
}
?>
So if $getDevitems returns
item_id | item_typet_id | item_identifier | expiration_timestamp
----------------------------------------------------------------------------
123 1 544 '2020-03-01 12:00:00'
I would want it to now run the comment select with 123 as the ID in the where clause:
select tc.item_id, tc.comment, tc.comment_type_id from development.item_commentt tc
inner join development.itemt t on tc.item_id = t.item_id
where t.item_id = 123
Now for my legacy parent record I have all of the parent data and all of the relational child data. so I want to insert the new parent record into the database, creating the new ID, and inserting the child record with the newly created primary key/ID. So for the new parent record I would do:
$insertitem = "INSERT into production (item_identifier,expiration_timestamp)
values (544,'2020-03-01 12:00:00')";
Let's say that creates the new record with item_id = 43409. I want my comment insert to be:
$insertComment = "INSERT into productionComment (item_id, comment, comment_type_id)
values (43409, comment, comment_type_id)";
Bottom LIne: I need to take relational data (all based on item_id) from a development database, and insert these into a new database which creates a new primary key but I need to keep the relationship.
How can I properly finish this to do what I need and make sure I maintain the full relationship for each originally selected item?
Given that your inserts are:
$insertitem = "INSERT into production (item_identifier,expiration_timestamp)
values (item_identifier,expiration_timestamp)";
$insertComment = "INSERT into productionComment (item_id, comment, comment_type_id)
values (item_id, comment, comment_type_id)";
It looks like you are using an identity column for item_id. You can retrieve the most recent generated identity value using the IDENTITY_VAL_LOCAL() function so the second insert should be:
$insertComment = "INSERT into productionComment (item_id, comment, comment_type_id)
values (IDENTITY_VAL_LOCAL(), comment, comment_type_id)";
I cannot help with PHP but with DB2 for IBMi you have different solutions :
If i understand it correctly item_id is a GENERATED ALWAYS as IDENTITY column
You can get newly created item_id using
select item_id from final table (
INSERT into production (item_identifier,expiration_timestamp)
values (544,'2020-03-01 12:00:00')
)
Or you can force value of item_id with dev value or your own increment
INSERT into production (idtem_id, item_identifier,expiration_timestamp)
values (<your value>, 544,'2020-03-01 12:00:00')
OVERRIDING SYSTEM VALUE
In this case you will have to set next value for item_id by issueing
alter table production alter column item_id restart with <restart value>
I have Postgres Query referring to which i am able to create query in laravel syntax for "select and then insert record".
Not able to apply "if exist, update record" in laravel query.
postgre query
INSERT INTO product_details (id, name, hash_id )
SELECT prod.id, d.name, MD5(CONCAT(d.name, LOWER(prod.id)))
FROM tmpTable tmp
INNER JOIN detailsTable d USING(name)
INNER JOIN productsTable prod ON (prod.id = tmp.id)
ON CONFLICT ON CONSTRAINT product_details_pkey1
DO UPDATE SET name = EXCLUDED.name;
Laravel Query
$query = DB::table('tmpTable AS tmp')
->join('detailsTable AS d', 'tmp.name','=', 'd.name')
->join('productsTable AS prod', 'prod.id','=','tmp.id')
->select('prod.id', 'd.name','MD5(CONCAT(d.name, LOWER(prod.id)))');
DB::table('product_details')->insertUsing(['id', 'name', 'hash_id'], $query);
you can use the "updateOrCreate" method which is provided by the laravel Link
I have the following two tables
Table player:
player_id (int)(primary)
player_name (varchar)
player_report_count (int)
Table report:
report_id (int)(primary)
player_id
report_description
report_location
Firstly I ask the user for the player_name and insert it into the player database. From here the player is given an id.
Then I tried to grab the value of the players report count and increment the current value by one (which isn't working).
This is followed by grabbing the playerId from the player table and then inserting into the corresponding column from the report table (also does not work).
When I insert some values into the database, the names, description and report are added to the database however the playerID remains at 0 for all entries and the player_report_count remains at a consistent 0.
What is the correct way to make these two features function? And also is there a more efficient way of doing this?
<?php
$records = array();
if(!empty($_POST)){
if(isset($_POST['player_name'],
$_POST['report_description'],
$_POST['report_location'])){
$player_name = trim($_POST['player_name']);
$report_description = trim($_POST['report_description']);
$report_location = trim($_POST['report_location']);
if(!empty($player_name) && !empty($report_description) && !empty($report_location)){
$insertPlayer = $db->prepare("
INSERT INTO player (player_name)
VALUES (?)
");
$insertPlayer->bind_param('s', $player_name);
$reportCount = $db->query("
UPDATE player
SET player_report_count = player_report_count + 1
WHERE
player_name = $player_name
");
$getPlayerId = $db->query("
SELECT player_id
FROM player
WHERE player_name = $player_name
");
$insertReport = $db->prepare("
INSERT INTO report (player_id, report_description, report_location)
VALUES (?, ?, ?)
");
$insertReport->bind_param('iss', $getPlayerId, $report_description, $report_location);
if($insertPlayer->execute()
&& $insertReport->execute()
){
header('Location: insert.php');
die();
}
}
}
Main issue here is you are getting player details before inserting it. $getPlayerId will return empty result always.
Please follow the order as follows.
Insert player details in to player table and get payerid with mysql_insert_id. After binding you need to execute to insert details to the table.
Then bind and execute insert report .
Then update the player table by incrementing report count with playerid which you got in step 1.
Note : use transactions when inserting multiple table. This will help you to rollback if any insert fails.
MySQL Query will return result object. Refer it from here https://stackoverflow.com/a/13791544/3045153
I hope it will help you
If you need to catch the ID of the last insterted player, This is the function you need if you're using PDO or if it's a custom Mysql Class, you need the return value of mysql_insert_id() (or mysqli_insert_id()) and then directly use it in the next INSERT INTO statement
Currently trying to find a way to do the following inside some form of loop (preferably without a performance hit on database).
I have 3 tables user_hours, user_calendar and hours_statistics. I need to first do:
SELECT user_calendar.date_start,
user_calendar.opportunity_id,
user_hours.user_id,
user_hours.agreed_hours,
user_hours.completed_hours,
user_hours.hours_committed
FROM user_calendar
JOIN user_hours
ON user_calendar.user_calendar_id = user_hours.user_calendar_id
WHERE user_calendar.date_start = CURRENT_DATE()
AND user_hours.completed_hours IS NULL
AND user_hours.hours_committed = 'accepted'
This query could return like the following:
http://i.imgur.com/5cJ5v.png
So for each opportunity_id and user_id returned i'd like to then do:
UPDATE user_hours
SET completed_hours = agreed_hours,
hours_committed = 'completed'
WHERE opportunity_id = {opportunity_id}
AND user_id = {user_id}
AND hours_committed = 'accepted'
AND completed_hours IS NULL
Note that {opportunity_id} and {user_id} would need to be looped at this point (see screenshot) because we need to go through each user on each opportunity.
Then for each updated record i'd need to then get the total hours like:
// Get hours they have done to send to statistics data table
SELECT sum(completed_hours) FROM user_hours WHERE user_id = {user_id} AND opportunity_id = {opportunity_id}
// Get the completed hours total somehow as a variable
$completed_hours = (from result above)
// Commit stats
UPDATE hours_statistics SET completed_hours = (completed_hours+$completed_hours)
WHERE user_id = {user_id} AND opportunity_id = {opportunity_id}
Could anyone help write this as a procedure or a trigger of some kind or help me in the right direction to get a starting point for looping over this stuff? Manually the querying works, just need to be looped / automatic for a stats update to run.
You can create a trigger to update hours_statistics whenever user_hours is updated (you may also want to add similar triggers for INSERT and DELETE operations, depending on your application logic).
Assuming that a UNIQUE key has been defined on hours_statistics.(user_id, opportunity_id) one can use INSERT ... ON DUPLICATE KEY UPDATE within the trigger:
CREATE TRIGGER foo AFTER UPDATE ON user_hours FOR EACH ROW
INSERT INTO hours_statistics (user_id, opportunity_id, completed_hours) VALUES
(OLD.user_id, OLD.opportunity_id, -OLD.completed_hours),
(NEW.user_id, NEW.opportunity_id, +NEW.completed_hours)
ON DUPLICATE KEY UPDATE
completed_hours = completed_hours + VALUES(completed_hours);
Then you can use a single UPDATE statement (using the multiple-table syntax to join user_hours with user_calendar) to perform all of the updates on user_hours in one go, which will cause the above trigger to update hours_statistics as desired:
UPDATE user_hours JOIN user_calendar USING (user_calendar_id, opportunity_id)
SET user_hours.completed_hours = agreed_hours,
user_hours.hours_committed = 'completed'
WHERE user_hours.hours_committed = 'accepted'
AND user_hours.completed_hours IS NULL
AND user_calendar.date_start = CURRENT_DATE();