Calling SELECT Statements with parameters is great and makes life coding so tidy. My problem comes to when I want to update data in the database using an UPDATE statement.
I have the Stored Proc with the UPDATE statement included, similar to this below
CREATE DEFINER = 'myuser'#'%'
PROCEDURE sp_upd_planning (
IN prop_id int(11),
IN planned_date varchar(15),
IN time_slot int(11),
IN by_who int(11),
IN cost decimal(15,2),
IN complete_date varchar(15),
IN lastupd_user varchar(100))
BEGIN
UPDATE planning
SET
Status = CASE
WHEN CompleteDate IS NOT NULL THEN 4
WHEN PlannedDate IS NULL THEN 2
WHEN PlannedDate IS NULL AND CompleteDate IS NULL THEN 3
END
,PlannedDate = planned_date
,BookingDate = NOW()
,TimeSlot = time_slot
,ByWho = by_who
,Cost = epc_cost
,Complete = CASE WHEN CompleteDate IS NOT NULL THEN 1 ELSE 0 END
,CompleteDate = complete_date
,LastUpdateDate = NOW()
,LastUpdateUser = lastupd_user
WHERE PropID = prop_id;
END
The statement works as should when I run the CALL sp_upd_planning(paramters here); within the database.
I'm using as a submit from a form, I've posted the relevant fields into variables and in my connection I call the Stored Proc again and as before in the database I use the variables to match the parameters needed like this (yes I know it's using mysql_ but I wanted to test quickly so I used this)
mysql_query("CALL sp_upd_planning('$planned', '$timeslot', '$bywho', '$cost', '$completed', '$inputby', $propid)") or die(mysql_error());
When the code executes all looks good and no errors and the main form submits as should with the jquery I set up, but when I check the database nothing is updated.
Why would this be?
It sounds like you aren't executing your statement. In PHP you still have to execute the statement after creation. Also if I remember correctly it is more secure to bind your parameters instead of pass them in the string. Try something like this:
$conn = new mysqli("mysql:host=$host;dbname=$dbname", $username, $password);
// execute the stored procedure
$sql = "CALL sp_upd_planning(:planned, :timeslot, :bywho, :cost, :completed, :inputby, :propid)";
$stmt = $conn->prepare($sql);
$stmt->bindParam('datatypes', $planned, $timeslot, $bywho, $cost, $completed, $inputby, $propid);
$stmt->execute();
Basically by the term datatypes lets assume the planned is a string, timeslot is a date/time, bywho is a string, cost is an int, completed is an int, inputby is a string, and propid is an int then it would say 'sdsiisi'
Related
This question already has answers here:
PHP: Calling MySQL Stored Procedure with Both INPUT AND OUTPUT Parameters (NOT "INOUT")
(2 answers)
Closed 3 years ago.
To call a Stored procedure with an IN parameter is easy like
CREATE PROCEDURE `catalog_delete_product`(IN `inProductId` INT) BEGIN DELETE FROM product_attribute WHERE product_id = inProductId; DELETE FROM product_category WHERE product_id = inProductId; DELETE FROM shopping_cart WHERE product_id = inProductId; DELETE FROM product WHERE product_id = inProductId; END
You can see that it is as easy as that. But how do we call an OUT parameter in MySQL Stored parameter and use it in PHP?
As an example to illustrate it, I will a real world practical example(inserting data into an order table and returning the lastInsertId).
CREATE PROCEDURE `shopping_cart_create_order`(IN `inCartId` INT(11), OUT `newOrderId` INT(11)) BEGIN
DECLARE newOrder int;
-- Insert a new record into orders and obtain the new order ID
INSERT INTO orders (created_on) VALUES (NOW());
-- Obtain the new Order ID
SELECT LAST_INSERT_ID() INTO newOrder;
SET newOrder = newOrderId;
END
At PHP level// Probably at the Model/Entity level First, we need to execute the
shopping_cart_create_order()
stored procedure. Which might probably be in a function.
Second, to get the last order id, we need to query it from the variable
#oid
. It is important that we must call the method
closeCursor()
of the PDOStatement object in order to execute the next SQL statement.
function query($pdo, $sql, $parameters = []){
$query = $pdo->prepare($sql);
$query->execute($parameters);
return $query;
}
function create_order($pdo, $cart_id){
// Binding the parameters
$parameters = [':cart_id' => $cart_id];
// calling stored procedure command
$sql = 'CALL shopping_cart_create_order(:cart_id)';
// prepare for execution of the stored procedure, pass value to the command
and execute the Stored Procedure
$query = query($pdo, $sql, $parameters);
// Then close Cursor. It is important for you to close it.
$query->closeCursor();
// execute the second query to get last insert id
$row = $pdo->query("SELECT #oid AS oid")->fetch();
return $row;
}
I wrote a stored procedure in mysql, which does an insert into a table and the selects a field(id), so that it later be assigned to a php variable, to eventually pass it as a parameter to another mysql procedure. The first procedure works fine when I call it from mysql, it returns the value it was meant to. The problem lays on when I try to obtain that value from php.
Heres my code:
DELIMITER $
CREATE PROCEDURE addEntity(p_idPerson INT(11),
p_nameP VARCHAR(50), p_objective VARCHAR(8),
OUT p_idProduct INT(11)
)
BEGIN
INSERT INTO EntityTb (idPerson, nameP, objective) VALUES(p_idPerson, p_nameP, p_objective);
SET p_idProduct= (SELECT idProduct FROM EntityTb WHERE idPerson= p_idPerson ORDER BY idProduct DESC LIMIT 1);
SELECT p_idProduct;
END$
DELIMITER;
PHP
$prep_stmt = "CALL addEntity(?,?,?,?)";
$insert_stmt = $mysqli->prepare($prep_stmt);
$p_id= "#p_idProduct";
if ($insert_stmt) {
$insert_stmt->bind_param('issi', $arg1, $arg2, $arg3 $p_id);
$insert_stmt->execute();
while ($rs= $insert_stmt->fetch()) {
//debug($rs);
echo "\r\n rs: ".$rs;
}
}
I fixed it. Just had to change the php code above to the one below.
$insert_stmt= $mysqli->query("CALL addProduct($arg1, '$arg2', '$arg3', #p_idProduct)");
if ($insert_stmt->field_count)
{
$rs= $insert_stmt->fetch_assoc();
$id_prod= $rs['p_idProduct'];
echo "id_product: ".$id_product;
}
I have a MSSQL table users:
CREATE TABLE users (
ID int IDENTITY(1,1) NOT NULL,
firstname nvarchar(20) NOT NULL,
lastname nvarchar(20) NOT NULL,
dir bit NOT NULL,
cc nvarchar(15),
readyacc bit NOT NULL,
region nvarchar(50),
org nvarchar(50),
suborg nvarchar(50),
section nvarchar(50),
title nvarchar(50),
floor tinyint,
wkstn nvarchar(50),
fc nvarchar(15)
);
And I'm trying to update an existing entry with the prepared query:
UPDATE users SET ? = ? WHERE ID=?;
With my parameters as:
Array ( [0] => title [1] => Teleco [2] => 1 )
But it seems as though if the string length is greater than 5 it gives me the error "String or binary data would be truncated.". Eg, Telec works but Teleco does not. When I try the same query in the SQL Management Studio it gives me no errors.
Am I just missing something obvious? Please help
Seeing someone else decided to post an answer, transcribing my comment to an answer.
That's just it, you can't bind tables/columns with UPDATE users SET ? = ? WHERE ID=?;.
Use a safelist if anything.
You can do this though $var="x"; by assigning a pre-defined variable "ahead of time".
Then doing UPDATE users SET '$var' = ? WHERE ID=?;
You see, tables/columns require a hard coded value or a "lookahead" in order to know what it's supposed to use as far as table/column names go, before binding begins. This all happens "after" the query, therefore a "lookahead" can be in the form of a variable.
FYI: The same applies for MySQL and is not specific to MSSQL.
Your query, when the parameters are passed in, it equivalent to this:
UPDATE users SET 'title' = 'Teleco' WHERE ID='1';
Which would not work if you tried running it in the management studio. The error message you're getting is erroneous. As the comment by Fred says, you need to have a safe(white) list of columns that can be updated:
$safe_cols = ['dir', 'cc', 'title'];
if(in_array($col, $safe_cols, true))
{
$stmt = $db->prepare('UPDATE users SET ' . $col . ' = ? WHERE id = ?');
// bind params and execute
}
I’ve a procedure in SQL Server 2008
CREATE PROCEDURE dbo.testing
#parm varchar(10),
#parmOUT varchar(30) OUTPUT
AS
BEGIN
SELECT #parmOUT = 'parm 1 ' + #parm
END
and i have a query to access this procedure in Codeigniter frameword.
i use sqlsrv_driver database.
$param1 = 'test';
$param2 = '1';
$this->db->query("dbo.testing ?, ?", array($param1, $param2));
i’ve execute the procedure, but i can’t retrieve 2nd parameter value ($param2).
Anyone have idea to get this 2nd parameter value??
thanks b4
In your Stored Procedure ,you are passing one input parameter and the specifying one output parameter . So the SP should be modified like the one below
ALTER PROCEDURE dbo.testing
#parm varchar(10),
#parmOUT varchar(30) OUTPUT
AS
BEGIN
SELECT 'parm 1 ' + #parm
END
Now in order to execute the above SP you need to pass just one input parameter
declare #out varchar(30)
exec testing 'test', #parmOUT=#out OUTPUT
You will just retrieve the result as
param1test
There is no second parameter which you can retrieve from your SP .The only value which you will get is the one which you have specified in your select query .
$sql = 'DECLARE #RETURNV VARCHAR(20)
EXEC dbo.testing ?, #parmOUT= #RETURNV OUTPUT
SELECT #RETURNV AS RETURNV';
$param = array(
"This is first param"
);
$temp = $this->db->query($sql, $param);
$result = $temp->result_array();
echo "<pre>".print_r($result, true)."</pre>";
I am having difficulty figuring out how to add data as input to an Oracle cursor being sent to a stored procedure of a package in PHP.
I am trying to send 2 pieces of data through a cursor. I have verified the data is correct up to sending.
PHP Code:
$finalpieces = explode('|',$lkeyarr[$i]); //0=unique id, 1=table
$conn = oci_connect($oracleUsername,$oraclePassword,$oracleService);
$stmt = OCIParse($conn,"BEGIN PROD.PKG_CORE_OBSERVER.StuckPages_Unlock(:cur_PageDetails); END;");
$cur = oci_new_cursor($conn);
OCIBindByName($stmt,':cur_PageDetails',$cur,-1,OCI_B_CURSOR);
ociexecute($stmt,OCI_DEFAULT);
Stored Procedure Details:
PROCEDURE StuckPages_Unlock
(
cur_PageDetails IN OUT SYS_REFCURSOR
)
accepts ref cursor that includes 2 fields:
ProcessID NUMBER(2);
PageUniqueID NUMBER(10);
Any help would be greatly appreciated.
A Ref Cursor is a pointer to a result set. We cannot assign values to a Ref Cursor, we use it with a query:
open my_ref_cursor for
select process_id, page_unique_id
from some_table;
So, your approach is wrong. It is difficult to be sure what you're trying to achieve but I think what you want is a stored procedure which accepts two parameters that it uses to query a table and return a ref cursor. Perhaps, something like this:
PROCEDURE StuckPages_Unlock
(
p_proc_id in some_table.process_id%type
, p_page_id in some_table.page_unique_id_id%type
, cur_PageDetails OUT SYS_REFCURSOR
)
IS
open PageDetails for
select *
from some_table
where process_id = p_proc_id
and page_unique_id = p_page_id;
END;