Retrieve output variable from MySQL stored procedure using CakePHP - php

I'm attempting to call a stored procedure using CakePHP.
Currently the returned values are comprised of the first recordset from the first SQL select statement in the stored procedure.
Even though the output variable is set in the stored procedure (ie. select #project_id into project_id), it doesn't show in the var_dump of the query result.
Stored Procedure:
CREATE DEFINER = 'admin'#'%'
PROCEDURE thebuggenie.cmdb_project_team_init(
IN project_name VARCHAR(200),
IN project_key VARCHAR(200),
IN project_homepage VARCHAR(200),
IN team_name VARCHAR(200),
OUT project_id INT(10))
BEGIN
-- start transaction
start transaction;
-- init variables
set #project_id = 0;
set #team_id = 0;
set #assoc_count = 0;
set #scope_id = 1;
-- select team and set variable
select #team_id := id
from tbg3_teams
where name = team_name;
-- if team_id = 0, insert team and set variable
if #team_id is NULL or #team_id = '' or #team_id = 0 then
-- insert new project
insert into tbg3_teams(ondemand, name, scope) values(0, team_name, #scope_id);
-- set team_id variable
set #team_id = LAST_INSERT_ID();
end if;
-- select project and set variable
select #project_id := id
from tbg3_projects
where name = project_name;
-- if project_id = 0, insert project and set variable
if #project_id is NULL or #project_id = '' or #project_id = 0 then
-- insert project
insert into tbg3_projects (name, locked, use_scrum, `key`, homepage, deleted, owner_team, scope, workflow_scheme_id, issuetype_scheme_id) values(project_name, 0, 1, project_key, project_homepage, 0, #team_id, #scope_id, 1, 1);
-- set project_id variable
set #project_id = LAST_INSERT_ID();
end if;
select #assoc_count := count(*)
from tbg3_projectassignedteams
where uid = #team_id
and project_id = #project_id;
if(#assoc_count = 0 and #project_id > 0 and #team_id > 0) then
insert into tbg3_projectassignedteams (project_id, role_id, uid, scope) values(#project_id, 35, #team_id, #scope_id);
end if;
-- setup default views
INSERT INTO tbg3_dashboard_views (name, view, pid, tid, target_type, scope) VALUES (101, 0, 0, #project_id, 2, 1);
INSERT INTO tbg3_dashboard_views (name, view, pid, tid, target_type, scope) VALUES (102, 0, 0, #project_id, 2, 1);
INSERT INTO tbg3_dashboard_views (name, view, pid, tid, target_type, scope) VALUES (110, 0, 0, #project_id, 2, 1);
INSERT INTO tbg3_dashboard_views (name, view, pid, tid, target_type, scope) VALUES (105, 0, 0, #project_id, 2, 1);
INSERT INTO tbg3_dashboard_views (name, view, pid, tid, target_type, scope) VALUES (106, 0, 0, #project_id, 2, 1);
INSERT INTO tbg3_dashboard_views (name, view, pid, tid, target_type, scope) VALUES (111, 0, 0, #project_id, 2, 1);
commit;
-- return values
select #project_id INTO project_id;
END
PHP Code:
$sql = "call thebuggenie.cmdb_project_team_init(";
$sql .= '\''.$results[0]['Asset']['project_name'].'\'';
$sql .= ',\''.$results[0]['Asset']['project_name'].'\'';
$sql .= ',\'\'';
$sql .= ',\''.$results[0]['Repository']['team_name'].'\'';
$sql .= ',#project_id';
$sql .= ');';
$sql .= 'select #project_id as project_id';
var_dump($sql);
$results = $this->Asset->query($sql);
print_r($results);
PHP Code outputs:
string 'call thebuggenie.cmdb_project_team_init('CMDB','CMDB','','team-app-platforms',#project_id);select #project_id as project_id;'
Array ( [0] => Array ( [0] => Array ( [#team_id := id] => 6 ) ) )
Note: I haven't finalized error trapping yet.

I ended up using this:
$sql = "call thebuggenie.cmdb_project_team_init(";
$sql .= '\''.$results[0]['Asset']['project_name'].'\'';
$sql .= ',\''.$results[0]['Asset']['project_name'].'\'';
$sql .= ',\'\'';
$sql .= ',\''.$results[0]['Repository']['team_name'].'\'';
$sql .= ',#project_id';
$sql .= '); select #project_id as project_id';
var_dump($sql);
$mysqli = new mysqli("DB_HOST", "DB_USER", "DB_PWD", "DATABASE");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$out = array();
if($mysqli->multi_query($sql))
{
do
{
if($result=$mysqli->store_result())
{
while($row=$result->fetch_row())
{
array_push($out, $row);
}
$result->free();
}
}while($mysqli->more_results() && $mysqli->next_result());
}
$mysqli->close();
$out[3][0] contained the value I was looking for.

Related

MySQL: Insert new record using MAX value of a column in the same table

I need to INSERT a new record, using the MAX value of the position column plus one, in the newly inserted row. So if the MAX value is 14, the next inserted row's position column value should be 15.
This is my current code, which is working but it needs 2 separate queries:
# get position order
$sql = 'SELECT MAX(position) FROM store_item_photo WHERE id_item = 3';
$stmt = cnn()->prepare($sql);
$stmt->execute();
$position = $stmt->fetchColumn();
$position++;
# photo: new record
$sql = 'INSERT INTO store_item_photo (id_item, position) VALUES (3, :position)';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':position', $position, PDO::PARAM_INT);
$stmt->execute();
I wanted to know if there is some way to achieve the same result with just one query:
# photo: new record (one query)
$sql = 'INSERT INTO store_item_photo (id_item, position) VALUES (3, (SELECT MAX(position) FROM store_item_photo WHERE id_item = 3) + 1)';
$stmt = cnn()->prepare($sql);
$stmt->execute();
That test is throwing an error. Is it possible to achieve this with a similar approach?
I built the schema in sqlfiddle: http://sqlfiddle.com/#!9/228058/1
If you want to use a subquery in an Insert you don't have to use VALUES
Try this query:
INSERT INTO store_item_photo (id_item, position)
SELECT
3 AS id_item,
MAX(position) + 1
FROM store_item_photo
WHERE id_item = 3;
Try this query :
$sql = 'INSERT INTO store_item_photo (id_item, position) VALUES (3, ((SELECT MAX(position) FROM store_item_photo WHERE id_item = 3) + 1))';
$stmt = cnn()->query($sql);

Calling mysql procedure from php with in and out paramenter

Please help me out. I'm trying to insert the records in 2 tables, in 1st table I can insert but for the second table I can't.
I have 3 stored procedures
HotelInsert
GetAccommodationByName
AvailbiltyInsert
It seems like the 1st stored procedure is okay as I can get output in the first table but in the second table I can't get the last inserted id.
First stored procedure
DELIMITER $$
CREATE DEFINER=`kno`#`localhost` PROCEDURE `HotelInsert`(IN `ZIP` BIGINT, IN `Ammn` VARCHAR(255), IN `HotelName` VARCHAR(255), IN `Add1` VARCHAR(255), IN `Add2` VARCHAR(255), IN `Det` VARCHAR(255), IN `ContactPer` VARCHAR(255), IN `Contact` VARCHAR(255), IN `CEmail` VARCHAR(255), IN `Image` VARCHAR(255), IN `StarCateg` TINYINT)
NO SQL
DETERMINISTIC
INSERT INTO Accommodation(
AccommodationId,
AccommodationTypeId,
ZipId,
PackageId,
Amenities,
Name,
AddressOne,
AddressTwo,
AccommodationStatus,
Details,
ContactPerson,
StarCategory,
ImageGallery,
ContactPhone,
ContactEmail
)
VALUES(
NULL,
1,
ZIP,
4,
Ammn,
HotelName,
Add1,
Add2,
1,
Det,
ContactPer,
StarCateg,
Image,
Contact,
CEmail
)$$
DELIMITER ;
Second stored procedure:
DELIMITER $$
CREATE DEFINER=`kno`#`localhost` PROCEDURE `GetAccomodationIdByName`(IN `AccommodationName` VARCHAR(255), OUT `AccId` INT)
NO SQL
DETERMINISTIC
SELECT AccommodationId into AccId from Accommodation where Name=AccommodationName$$
DELIMITER ;
Third stored procedure:
DELIMITER $$
CREATE DEFINER=`kno`#`localhost` PROCEDURE `AvailabilityInsert`(IN `AccId` INT, IN `RTypeId` INT, IN `AvailableRooms` INT, IN `Charges` BIGINT, IN `AvailDate` DATE)
NO SQL
INSERT INTO AccommodationAvailabilty (AvailableId, AccommodationId, RoomTypeId, Available, Price, AvailableDate) VALUES (NULL, AccId, RTypeId, AvailableRooms, Charges, AvailDate)$$
DELIMITER ;
PHP code:
$sql = $db->prepare('CALL HotelInsert(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
$sql->bind_param('dssssssssss', $ZipId, $Amenities, $Name, $AddressOne, $AddressTwo, $Details, $ContactPerson, $ContactPhone, $ContactEmail , $target_path, $StarCategory);
$sql->execute();
$select = $db->query('SELECT #ZIP,#Ammn, #HotelName, #Add1, #Add2, #Det, #ContactPer,#Contact,#CEmail,#Image, #StarCateg');
$result = $select->fetch_assoc();
$ZipId = $result['#ZIP'];
$Amenities = $result['#Ammn'];
$AccommodationName = $result['#HotelName'];
$AddressOne = $result['#Add1'];
$AddressTwo = $result['#Add2'];
$Details = $result['#Det'];
$ContactPerson = $result['#ContactPer'];
$ContactPhone = $result['#Contact'];
$ContactEmail = $result['#CEmail'];
$target_path = $result['#Image'];
$StarCategory = $result['#StarCateg'];
//Hotel Calling AccommodationId by AccommodationName with GetAccomodationIdByName(); stored procedure.
$sql = $db->prepare('CALL GetAccomodationIdByName(?)');
$sql->bind_param('s', $AccommodationName);
$sql->execute();
$select = $db->query('SELECT #AccId');
$result = $select->fetch_assoc();
$AccommodationId = $result['#AccId'];
//Hotel Insert RoomType by calling AvailabilityInsert(); Store procedure.
$sql = $db->prepare('CALL AvailabilityInsert(?,?,?,?,?)');
$sql->bind_param('iiids', $AccommodationId, $RoomTypeId, $Available, $Price, $AvailableDate);
$sql->execute();
$select = $db->query('SELECT #AccId,#RTypeId, #AvailableRooms, #Charges, #AvailDate');
$result = $select->fetch_assoc();
$AccommodationId = $result['#AccId'];
$RoomTypeId = $result['#RTypeId'];
$Available = $result['#AvailableRooms'];
$Price = $result['#Charges'];
$AvailableDate = $result['#AvailDate'];
header("Location: ../hotel-all.php?id=$Name");
exit();

Running an SQL query multiple times

I need to run this query 100 times to input data into my MySQL database. ID auto increments. Not concerned about incrementing the table Name column. Just need to fill the database. What is the best way to go about this without having to copy/paste 100 times?
"INSERT INTO `tables`(id, name, assigned_seating, open_seating, position) VALUES ('', 'Table 1', 0, 1, '')";
All you need is an existing table with at least 100 rows. I will use information_schema.columns as example:
INSERT INTO `tables`(id, name, assigned_seating, open_seating, position)
SELECT null, 'Table 1', 0, 1, ''
FROM information_schema.columns
LIMIT 100;
Demo: http://rextester.com/DMSC23853
If anyone sees this in the future, this is the best answer
public function addbatch()
{
for ($i = 1; $i <= 100; $i++)
{
$tableName = "Table " . $i;
$q = "INSERT INTO `tables`(id, name, cap, assigned_seating, open_seating, position) VALUES ('', '".$tableName."', 10, 0, 1, '')";
$this->db->query($q);
}
}
call function once. Make sure to delete when done though!
You can do a Batch insert:
insert into Table
(column1, column2)
VALUES
('value 1', 'value2') ,
('value3', 'value4')
You can do as many rows as you want as long as you separate them by comas.
$vals='';
for ($i = 0; $i < 100; $i++) {
$vals.="('Table 1', 0, 1, ''),";
}
$vals=rtrim($vals,',');
mysqli_query($dbh, 'INSERT INTO `tables`(name, assigned_seating, open_seating, position) VALUES ' . $vals);
assumed id was auto incremented so just leave it out of the query
try this:
DELIMITER $$
DROP PROCEDURE IF EXISTS `multipleInsert` $$
CREATE PROCEDURE `multipleInsert`(in n int)
BEGIN
DECLARE cont int default 0;
WHILE cont < n DO
INSERT INTO `tables`(id, name, assigned_seating, open_seating, position) VALUES ('', 'Table 1', 0, 1, '');
set cont = cont + 1;
end while;
END $$
DELIMITER ;
Call Procedure:
call multipleInsert(100);

SELECTING Multiple Rows with an Array and then INSERT to another statement

I am trying to SELECT data from one table based on the ID and then INSERT the returned data in to another table.
My code is:
<?php
require '../../db-config.php';
if(isset($_POST['course'])) {
$selected_courses = '('. implode(',', $_POST['course']) .')';
$status = 'Live';
$active = 'Y';
$stmt = "SELECT id, coursetitle FROM courses WHERE id IN ". $selected_courses ."
AND status = ?";
$stmt = $conn->prepare($stmt);
$stmt->bind_param('i', $selected_courses);
$stmt->execute();
$stmt->bind_result($id, $coursetitle);
while($stmt->fetch()) {
$stmt = $conn->prepare("INSERT INTO distributor_course_settings
(id, active, coursetitle) VALUES (?, ?, ?)");
$stmt->bind_param("iss", $id, $active, $coursetitle);
$stmt->execute();
}
}
?>
The error I am getting is: PHP Fatal error: Call to a member function
bind_param() on boolean
What is wrong with my code?
you can perform both actions (select and insert) in one query. Something like this:
INSERT INTO distributor_course_settings
(id, distributor, active, coursetitle)
SELECT id, '$distributer', 'Y', coursetitle
FROM courses
WHERE id IN ". $selected_courses ."
AND status = 'Live'
the values in select statement can be anything like string, php variable or a subselet statment like:
INSERT INTO distributor_course_settings
(id, distributor, active, coursetitle)
SELECT id, (select distributer from distributor_course_settings where id = 12), 'Y', coursetitle
FROM courses
WHERE id IN ". $selected_courses ."
AND status = 'Live'
and if its a php variable, you statement could look like this:
$stmt = "INSERT INTO distributor_course_settings
(id, distributor, active, coursetitle)
SELECT id, '".$distributor."', 'Y', coursetitle
FROM courses
WHERE id IN ". $selected_courses ."
AND status = 'Live'"

Insert statement with primary key and scope identity

I want to get the the primary key (auto_increment) for the latest record to use it as a foreign key in the other table. When I use the SCOPE_IDENTITY() as a pdo parameter, I get the error:
Call to undefined function SCOPE_IDENTITY().
When I use it as a direct value, the statement always rolls back.
Is my code correct?
if (empty($errors)) {
$sqlconnection = new SqlConnection();
$conn = $sqlconnection->db_connect();
if ($conn) {
if (sqlsrv_begin_transaction($conn) === false ) {
$errors[] = "Cant start transaction.";
} else {
// Query1
$query1 = "INSERT INTO [RC.table1] (terminname, datum) VALUES (?, ?)";
$params1 = array($eventname, $eventdate);
$stmt1 = sqlsrv_query($conn, $query1, $params1);
//Query2
$query2 = "INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES ((SELECT SCOPE_IDENTITY()), ?)";
$params2 = array($_SESSION['mandant_id']);
$stmt2 = sqlsrv_query($conn, $query2, $params2);
if($stmt1 && $stmt2) {
sqlsrv_commit( $conn );
echo "Transaction committed.<br />";
} else {
sqlsrv_rollback( $conn );
echo "Transaction rolled back.<br />";
}
}
} else {
$errors[] = "Cant connect to database.";
}
}
Try this solution: replace
$query2 = "INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES ((SELECT SCOPE_IDENTITY()), ?)";
with this:
$query2 = "DECLARE #LastID INT; SET #LastID = SCOPE_IDENTITY(); INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES (#LastID, ?)";
Also, for #LastID variable definition (DECLARE #LastID INT) please use the same data type as data type of appointment_id column. In this example, I assumed that #LastID's type is INT.
Edit: You could create the following stored procedure with TRY ... CATCH:
CREATE PROCEDURE dbo.Insert_Table1Table2
(
#terminname NVARCHAR(50),
#datum DATE,
#mandant_id INT
)
AS
BEGIN
BEGIN TRANSACTION;
BEGIN TRY
INSERT INTO [RC.table1] (terminname, datum) VALUES (#terminname, #datum)
DECLARE #appointment_id INT;
SET #appointment_id = SCOPE_IDENTITY();
INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES (#appointment_id, #mandant_id)
END TRY
BEGIN CATCH
SELECT
DECLARE #ErrorMessage NVARCHAR(2048);
SET #ErrorMessage = ERROR_MESSAGE();
RAISERROR(#ErrorMessage, 16, 1)
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
END
Note: You should replace every type and max. length with the proper type and length.
BEGIN TRAN T1;
INSERT INTO [RC.table1] (terminname, datum) VALUES ('alibaba', '24.02.2014');
BEGIN TRAN T22
INSERT INTO [RC.table2] (appointment_id, mandant_id) VALUES ((SELECT SCOPE_IDENTITY()), '0200')
COMMIT TRAN T1;
COMMIT TRAN T2;
that works perfectly in the studio. dont know, why I cant get the identity in the php transaction.
By the way, while that code MIGHT work, I would suggest the following changes...
$query1 = "INSERT INTO [RC.table1] (terminname, datum) VALUES (?, ?);select ##identy"
now, retrieve the result (which will be the new key added) and pass it as a parameter to the next SQL call.

Categories