Executing an Oracle procedure using PHP - possible? - php

I'm trying to run a very simple Oracle procedure from PHP, using the following statement:
$sql = 'exec procedureName(param1, param2)';
$sql = oci_parse($connection, $sql); oci_execute($sql);
Running this in Oracle SQL developer returns a successful 'anonymous block completed' message, but running this via PHP returns an 'ORA-00900: invalid SQL statement' error.
Is there anyway to run this procedure from PHP? Many thanks

Looking a little deeper, I think you'll need to put your procedure call inside a PL/SQL BEGIN-END pair, as in:
$sql = 'BEGIN procedureName(:param1, :param2); END;';
$stmt_id = oci_parse($connection, $sql);
oci_bind_by_name($stmt_id, ':param1', $value1);
oci_bind_by_name($stmt_id, ':param2', $value2);
oci_execute($stmt_id);
You'll need to edit the above to use whatever variable names are appropriate in the calls to oci_bind_by_name.
Also note that the presence of semi-colons in the SQL string is important.
Share and enjoy.

$sql = 'BEGIN procedureName(:param1, :param2); END;';
$stmt_id = oci_parse($connection, $sql);
oci_execute($stmt_id);

Related

How to use a $_POST variable in an mysqli-query? (php)

I'm currently learning php and am testing around with sqli queries.
I want to have an input field where a number can be entered. This number is used in the sql-query. Unfortunately it doesn't work the way I want.
The text field is stored in index.php as this:
<form method="post" action="handler.php">
<input type="text" name="idEingabe">
<input type="submit" value="Abfrage für eingegebene ID starten">
</form>
In handler.php, I'm using
$stridEingabe = $_POST["idEingabe"];
And the query contains:
$query = 'SELECT name, beschreibung FROM uebersicht WHERE id = "$stridEingabe"';
$result = mysqli_query($con, $query);
if ($result = mysqli_query($con, $query)) {
/* Array ausgeben */
while ($row = mysqli_fetch_assoc($result)) {
printf ("<b>%s</b> <br>%s<br> <br>", $row["name"], $row["beschreibung"]);
}
/* free result set */
mysqli_free_result($result);
}
mysqli_close($con);
?>
Unfortunately I don't get any results when I enter the number into the text box and click the submit-button. But if I write the number in the query without using $stridEingabe, I'm getting the results.
Where is the mistake?
Thanks a lot
Seeing that an answer's been submitted before this, thought I'd put one in too and based on a comment I left under the question.
One of the problems here is, you're querying twice which is a major issue, resulting in a syntax error that MySQL is throwing in the background, but you're not listening for it. Plus, your quoting method which I've modified below, just in case it is a string; which we don't know at this time.
$query = 'SELECT name, beschreibung FROM uebersicht WHERE id = "$stridEingabe"';
$result = mysqli_query($con, $query);
^^^^^^^^^^^^
if ($result = mysqli_query($con, $query)) {
^^^^^^^^^^^^
/* Array ausgeben */
while ($row = mysqli_fetch_assoc($result)) {
printf ("<b>%s</b> <br>%s<br> <br>", $row["name"], $row["beschreibung"]);
}
what you want is to remove = mysqli_query($con, $query) and add error checking:
$query = "SELECT name, beschreibung FROM uebersicht WHERE id = '".$stridEingabe."'";
$result = mysqli_query($con, $query);
if ($result) {
/* Array ausgeben */
while ($row = mysqli_fetch_assoc($result)) {
printf ("<b>%s</b> <br>%s<br> <br>", $row["name"], $row["beschreibung"]);
}
} // brace for if ($result)
// else statement for if ($result)
else{
echo "There was an error: " .mysqli_error($con);
}
Or, better yet using mysqli_real_escape_string().
$stridEingabe = mysqli_real_escape_string($con,$_POST["idEingabe"]);
Although prepared statements are best.
Plus, in regards to SQL injection which is something you're open to, should be using mysqli with prepared statements, or PDO with prepared statements, they're much safer.
Footnotes:
Make sure you are indeed using mysqli_ to connect with and not another MySQL API such as mysql_ or PDO to connect with. Those different APIs do not intermix with each other.
I say this because, the connection method is unknown in your question.
Plus, if you're using your entire code inside the same file, then you should be using a conditional statement for your POST array, otherwise it will thrown a notice immediately on page load; assuming error reporting is enabled on your system.
The notice would be "Undefined index idEingabe..."
I.e.:
if(!empty($_POST['idEingabe'])){...}
Another thing; if your inputted value is an integer, you can use the following functions to make sure they are integers and not a string, if that is what the ultimate goal is:
http://php.net/manual/en/function.is-int.php - is_int()
http://php.net/manual/en/function.is-numeric.php - is_numeric()
and using a conditional statement in conjunction with those.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// rest of your code
Sidenote: Error reporting should only be done in staging, and never production.
Two things, first your quotes are wrong, and second, with your code you are vulnerable to sql code injection attacks, try this instead:
$stridEingabe = mysql_real_escape_string($_POST["idEingabe"]);
$query = "SELECT name, beschreibung FROM uebersicht WHERE id='$stridEingabe'";
The problem is that you are not concatenating the $string to the query
Use something like
$query = 'SELECT name, beschreibung FROM uebersicht WHERE id = ''.$stridEingabe.'';
Or use double quotes which is way more acceptable
$query = "SELECT name, beschreibung FROM uebersicht WHERE id = '$stridEingabe'";
And try to use only the $results declared in the if statement to avoid double queries.
You are using wrong quotes. try this:
$query = "SELECT name, beschreibung FROM uebersicht WHERE id = '$stridEingabe'";

PHP PDO interface with MS SQL Server

I am having trouble with using PHP PDO interface with Microsoft SQL Server. The problem is with converting PHP number values to use in functions of MS SQL Server. I use the following statement to delete certain records:
$sql = "DELETE FROM table WHERE SUBSTRING(attribute, 1, ?) = ?";
I prepare and execute this statement with code (a little shrinked):
$query = $pdo->prepare ($sql);
$query->execute (array (strlen ('Text'), 'Text'));
But the query always fails. The error is:
SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Argument data type nvarchar is invalid for argument 3 of substring function.
I am assuming the number from strlen is not parsed into a number, but I don't know how to fix this (except to manually add into the query).
I have found these links, however not very helpful.
http://social.msdn.microsoft.com/Forums/en-US/sqldriverforphp/thread/0f09ac5e-62cd-4ccf-b2cb-848aad23811e
http://drupal.org/node/1169202
The guys on Drupal had same error, but they fixed it with recreating function with casts. Is there any other way to fix this?
Thanks.
Not sure if this will solve it, but try something like this
$length = strlen('Text');
$text = "Text";
$sql = "DELETE FROM table WHERE SUBSTRING(attribute, 1, :len) = :text";
$query = $pdo->prepare ($sql);
$query->bindParam(':len', $length, PDO::PARAM_INT);
$query->bindParam(':text', $text, PDO::PARAM_STR);
$query->execute();
Try:
$query = $pdo->prepare ($sql);
$query->execute (array ((int) strlen ('Text'), 'Text'));

Returning a Table over OCI8 from Oracle Stored Procedure

I am connecting to Oracle via OCI8.
I have a stored procedure:
PROCEDURE ocigetaccounts(accounts OUT SYS_REFCURSOR)
IS BEGIN
OPEN accounts FOR
SELECT * FROM tbaccounts;
END ocigetaccounts;
And I am attempting to return it to PHP using OCI:
$sqlString = 'BEGIN accounts.ocigetaccounts(:accounts); END;';
oci_bind_by_name($statement, ':accounts', $result, -1);
echo $result;
(The rest of the required php-side OCI is in place.)
The error I am getting is:
Warning: oci_execute(): ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'OCIGETACCOUNTS'
How can I get $result to container the table resource
As far as I can tell, $result will contain the resource you are after.
The error you are getting is because the cursor is not defined as a type cursor.
You have to explicitly define $result as a cursor
$result = oci_new_cursor( $dbci );
If $result is returned, it will be returned as a resource and you should handle it just as you would handle a any other returned resource.
For your example (with $dbci being your connection resource):
$sqlString = 'BEGIN accounts.ocigetaccounts(:accounts); END;';
$stmt = oci_parse ( $dbci, $sqlString );
//Declare cursor
$result = oci_new_cursor( $dbci );
//Bind cursor
oci_bind_by_name ( $stmt, ':accounts', $result, -1, OCI_B_CURSOR);
//Execute query
if (oci_execute ( $stmt )) {
//Execute cursor
oci_execute($result); //Or you can return the cursor.
}
This is how we handle cursors returned from the database.
Hope this solves the problem
There are issues with PHP and REFCURSORS. See this excellent blog article for a complete explanation, and workaround:
http://blogs.oracle.com/opal/entry/converting_ref_cursor_to_pipe
Hope that helps.

How to use MySQLi Prepared Statements with Stored Procedures

I'm trying to learn more about MySQL and how to protect against SQL injections so my research has brought me to Prepared Statements which seems to be the way to go.
I'm also working on learning how to write Stored Procedures and am now trying to combine the two. There isn't much info on this though.
At the moment in my PHP test app I have a function that calls an SP with a normal MySQL command like this:
mysql_query("CALL usp_inserturl('$longurl', '$short_url', '$source')");
How can I do the same with MySQLi and a Prepared Statement to make it as safe as possible to injections?
Thanks!
Try the following:
$mysqli= new mysqli(... info ...);
$query= "call YourSPWithParams(?,?,?)";
$stmt = $mysqli->prepare($query);
$x = 1; $y = 10; $z = 14;
$stmt->bind_param("iii", $x, $y, $z);
$stmt->execute();
You can use both of them in the same time: just make preparation with stored procedure:
//prepare and bind SP's parameters with your variables only once
$stmt=$db->prepare("CALL MyStoredProc(?,?)");
$stmt->bind_param('is',$i,$name);
//then change binded variables and execute statement
for($i=1;$i<9;$i++)
{
$name="Name".$i;
$stmt->execute();
}
Bear in mind that you should do the preparation only once (not again for each execution), then execute it more times (just change parameter value before).
This one was a bit tricky but I eventually figured out how to both use a stored procedure (using IN parameters) that uses a prepared statement and retrieve the data through PHP. This example uses PHP 7.4.6 and MySQL 8.0.21 Community edition.
Here is the Stored Procedure:
CREATE DEFINER=`root`#`loalhost` PROCEDURE `SP_ADMIN_SEARCH_PLEDGORS`(
IN P_email VARCHAR(60),
IN P_password_hash VARCHAR(255),
IN P_filter_field VARCHAR(80),
IN P_filter_value VARCHAR(255)
)
BEGIN
#Takes admin credentials (first tow paramaters and searches the pledgors_table where field name (P_filter_field) is LIKE value (%P_filter_value%))
DECLARE V_admin_id INT(11);
BEGIN
GET DIAGNOSTICS CONDITION 1 #ERRNO = MYSQL_ERRNO, #MESSAGE_TEXT = MESSAGE_TEXT;
SELECT 'ERROR' AS STATUS, CONCAT('MySQL ERROR: ', #ERRNO, ': ', #MESSAGE_TEXT) AS MESSAGE;
END;
SELECT admin_id INTO V_admin_id FROM admin_table WHERE password_hash = P_password_hash AND email = P_email;
IF ISNULL(V_admin_id) = 0 THEN
SET #statement = CONCAT('SELECT pledgor_id, email, address, post_code, phone, alt_phone, contact_name
FROM pledgors_table
WHERE ',P_filter_field, ' LIKE \'%', P_filter_value, '%\';');
PREPARE stmnt FROM #statement;
EXECUTE stmnt;
ELSE
SELECT 'ERROR' AS STATUS, 'Bad admin credentials' AS MESSAGE;
END IF;
END
And here is the PHP script
query = 'CALL SP_ADMIN_SEARCH_PLEDGORS(\''.
strtolower($email).'\', \''.
$password_hash.'\', \''.
$filter_field.'\', \''.
$filter_value.'\');';
$errNo = 0;
//$myLink is a mysqli connection
if(mysqli_query($myLink, $query)) {
do {
if($result = mysqli_store_result($myLink)) {
while($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
mysqli_free_result($result);
}
} while(mysqli_next_result($myLink));
}
else {
$errNo = mysqli_errno($myLink);
}
mysqli_close($myLink);
You might find the following answer of use:
MySql: Will using Prepared statements to call a stored procedure be any faster with .NET/Connector?
In addition:
GRANT execute permissions only so your application level user(s) can only CALL stored procedures. This way, your application user(s) can only interact with the database through your stored procedure API, they can not directly:
select, insert, delete, update, truncate, drop, describe, show etc.
Doesn't get much safer than that. The only exception to this is if you've used dynamic sql in your stored procedures which I would avoid at all costs - or at least be aware of the dangers if you do so.
When building a database e.g. foo_db, I usually create two users. The first foo_dbo (database owner) is the user that owns the database and is granted full permissions (ALL) so they can create schema objects and manipulate data as they want. The second user foo_usr (application user) is only granted execute permisisons and is used from within my application code to access the database through the stored procedure API I have created.
grant all on foo_db.* to foo_dbo#localhost identified by 'pass';
grant execute on foo_db.* to foo_usr#localhost identified by 'pass';
Lastly you can improve your code example above by using mysql_real_escape_string:
http://php.net/manual/en/function.mysql-real-escape-string.php
$sqlCmd = sprintf("call usp_inserturl('%s','%s','%s')",
mysql_real_escape_string($longurl),
mysql_real_escape_string($shorturl),
mysql_real_escape_string($source));
$result = mysql_query($sqlCmd);

mysql stored procedures using php

I have a stored procedure:
delimiter //
create procedure userlogin(in eml varchar(50))
begin
select * from users
where email = eml;
end//
delimiter ;
And the php:
$db = new mysqli("localhost","root","","houseDB");
$eml = "tsubi#gmail.com";
$sql = $db->query("CALL userlogin('$eml')");
$result = $sql->fetch_array();
The error that I get from the browser when I run the php script:
Fatal error: Call to a member function fetch_array() on a non-object...
I am using phpmyadmin version 3.2.4 and mysql client version 5.1.41.
You have to use mysqli_multi_query, not query. Check
http://us.php.net/manual/en/mysqli.multi-query.php , they have a good example
mysqli::query returns false if the query fails (instead of returning a result object or true). You need to test whether the result actually is an object:
$sql = $db->query("CALL userlogin('$eml')");
if (is_object($sql))
$result = $sql->fetch_array();
else
printf("Error: %s\n", $sql->error);
You will probably get an error message explaining why calling the stored procedure didn*t work out.

Categories