I have a successful connection to SQL Server using SQLSRV in my PHP script:
$name = 'SERVERNAME';
$db = 'DBNAME';
$par = array("Database"=>$db);
$conn = sqlsrv_connect($name, $par);
Also I have the following T-SQL script:
Declare #dt datetime;
SET #dt = GETDATE();
EXEC oik..SrezLTGES #Cat = 'Ë', #Ids = '140539,140540,140589,150395,180395,180396,180445',#Time = #dt
The procedure parameters are:
I don't know how to execute this query in PHP. Any ideas?
A possible approach here is to parameterize the statement and use sqlsrv_query(). As is mentioned in the documentation, the sqlsrv_query function is well-suited for one-time queries and should be the default choice to execute queries unless special circumstances apply and sqlsrv_query function does both statement preparation and statement execution, and can be used to execute parameterized queries.
The stored procedure has varchar parameters (and I'm almost sure, that you are using a cyrillic collation), so you may need to use the appropriate encoding ("CharacterSet" => "UTF-8" or "CharacterSet" => SQLSRV_ENC_CHAR in the connection options) and/or character set conversion on the parameters values (with iconv() for example). Reading UTF-8 all the way through is a good starting point.
If the stored procedure returns data, you may try to use sqlsrv_fetch_array() to retrieve the returned data. You may also use SET NOCOUNT ON to prevent SQL Server from passing the count of the affected rows as part of the result set.
The following example, based on your code, is a possible solution to your problem:
<?php
// Connection
$server = "SERVERNAME";
$database = "DBNAME";
$cinfo = array(
"CharacterSet" => "UTF-8",
"Database" => $database
);
$con = sqlsrv_connect($server, $cinfo);
if ($con === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
// Statement
$sql = "
SET NOCOUNT ON;
DECLARE #dt datetime;
SET #dt = GETDATE();
EXEC oik..SrezLTGES
#Cat = ?,
#Ids = ?,
#Time = #dt,
#TimeIsSummer = 1,
#ShowSystemTime = 1
";
$params = array("Ë", "140539,140540,140589,150395,180395,180396,180445");
$stmt = sqlsrv_query($con, $sql, $params);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// Data
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
echo print_r($row, true);
}
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
?>
Related
I am trying to backup a MS SQL database calling a Stored Procedure using PHP.
When I execute de SP on SSMS, everything works fine. However, when I call it from the PHP script, I can see a ".bak" in the backup folder and right after the PHP finishes processing, the BackUp.bak file disappears.
Here is the Stored Procedure:
DECLARE #date VARCHAR(10)
SET #date = (SELECT date FROM tbl_date)
Declare #fileName VARCHAR(100)
SET #fileName = ('C:\db_backup\BackUp_' + #date + '.bak')
BACKUP DATABASE DbName
TO DISK = #fileName
WITH FORMAT,
MEDIANAME = 'SQLServerBackups',
NAME = 'Full Backup of DbName';
Below is the PHP code I call the SP:
$serverName = "server";
$connectionInfo = array( "Database"=>"DbName", "UID"=>"UserName", "PWD"=>"P#ssword", "CharacterSet"=>"UTF-8", "ReturnDatesAsStrings" => "false");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
$BackupDB = "Exec DBBackup";
sqlsrv_query($conn, $BackupDB);
I am running Apache 2.4.46 and SQL Server Express 2019.
My goal is to create a ".bak" file using PHP.
I tried using a SP because the original code is written in Classic ASP and it works flawlessly this way.
I am open to try different approaches.
Thank you.
Explanations:
You are using PHP Driver for SQL Server, so the following explanations are an additional option for solving your problem:
It seems that this issue is probably a driver specific problem. SQL Server fills the output buffer of the connection with the result sets that are created by the batch - information about the count of the affected rows (in a case of INSERT\DELETE\UPDATE statements for example) or progress status (returned from BACKUP\RESTORE DATABADE statements). These result sets must be processed by the PHP script. It seems that this behavior is by design and the PHP script should flush all the pending result sets. After the result sets are fetched, SQL Server completes the execution of the batch. The appropriate functions\methods that you need to use are sqlsrv_next_result() (for SQLSRV version of the driver) and PDOStatement::nextRowset() (for PDO_SQLSRV version of the driver).
For the SQLSRV version of the driver you need to change the error and warning handling using sqlsrv_configure("WarningsReturnAsErrors", 0);.
Examples:
I'm able to reproduce the issue from the question and the following examples are working solutions:
Using SQLSRV version of the driver:
<?php
// Server information
$server = "server\instance,port";
$database = "database";
$uid = "username";
$pwd = "password";
// Configuration
sqlsrv_configure("WarningsReturnAsErrors", 0);
// Connection
$cinfo = array(
"UID" => $uid,
"PWD" => $pwd,
"Database" => $database
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
echo "Unable to connect.";
die( print_r( sqlsrv_errors(), true));
}
// Statement
$sql = "
DECLARE #date VARCHAR(19)
SET #date = CONVERT(VARCHAR(19), GETDATE(), 126)
SET #date = REPLACE(#date, ':', '-')
SET #date = REPLACE(#date, 'T', '-')
DECLARE #fileName VARCHAR(100)
SET #fileName = ('d:\backup\BackUp_' + #date + '.bak')
BACKUP DATABASE dbname
TO DISK = #fileName
WITH
FORMAT,
STATS = 1,
MEDIANAME = 'SQLServerBackups',
NAME = 'Full Backup of dbname';
";
$stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) {
echo "Unable to execute query.";
die( print_r( sqlsrv_errors(), true));
}
// Clear buffer
while (sqlsrv_next_result($stmt) != null){};
echo "Success";
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
?>
Using PDO_SQLSRV version of the driver:
<?php
// Server information
$server = "server\instance,port";
$database = "database";
$uid = "username";
$pwd = "password";
// Connection
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
// Statement
$sql = "
DECLARE #date VARCHAR(19)
SET #date = CONVERT(VARCHAR(19), GETDATE(), 126)
SET #date = REPLACE(#date, ':', '-')
SET #date = REPLACE(#date, 'T', '-')
DECLARE #fileName VARCHAR(100)
SET #fileName = ('d:\backup\BackUp_' + #date + '.bak')
BACKUP DATABASE dbname
TO DISK = #fileName
WITH
FORMAT,
STATS = 1,
MEDIANAME = 'SQLServerBackups',
NAME = 'Full Backup of dbname';
";
try {
$stmt = $conn->prepare($sql);
$stmt->execute();
} catch (PDOException $e) {
die ("Error executing query. ".$e->getMessage());
}
// Clear buffer
try {
while ($stmt->nextRowset() != null){};
echo "Success";
} catch (PDOException $e) {
die ("Error executing query. ".$e->getMessage());
}
// End
$stmt = null;
$conn = null;
?>
I have stored procedures in SQL Server that output data as xml datatype. When I try to get the output parameter in PHP with PHP Driver for SQL Server (sqlsrv extension) and the string is longer than 4000 I get an SQL Error (SQLSTATE 01004 (Data truncated)).
Here is a short example:
Stored Procedure:
CREATE PROCEDURE pr_getlargexml
#xml xml OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #xml =
(
SELECT *
FROM largeTable
FOR XML RAW, ELEMENTS, TYPE, ROOT('xml')
);
END;
GO
PHP code:
$serverName = "localhost\SQL2012TEST";
$connectionInfo = array("Database" => "TEST", "UID" => "", "PWD" => "");
$conn = sqlsrv_connect($serverName, $connectionInfo);
if ($conn === false) {
die(print_r(sqlsrv_errors(), true));
}
$retval = '';
$query = sqlsrv_query($conn, 'EXEC pr_getlargexml ?',array(array(&$retval,SQLSRV_PARAM_OUT,SQLSRV_PHPTYPE_STRING('UTF-8'),SQLSRV_SQLTYPE_XML)));
if ($query === false) {
die(print_r(sqlsrv_errors(), true));
}
echo "<pre>";
\var_dump($retval);
echo "</pre>";
If the xml is shorter than 4000, it works fine. I also tried to use nvarchar(max) as datatype in sql and SQLSRV_SQLTYPE_NVARCHAR('max') in php as sqltype, but I get the same Error.
Has anyone a solution for my problem?
I've been looking all across the internet for help on this and have found nothing.
Basically I need to know how to update a SQL Server VARBINARY(MAX) column with the hex of an image uploaded from a HTML form. The database is in a different place to the HTML form, so move_uploaded_file in PHP then OPENROWSET (BULK ...) in SQL doesn't work (unable to find the file).
I also tried doing file_get_contents on the uploaded $_FILE['name_']['tmp_name'], then used unpack("H*hex") and put the result of that into the SQL column with a "0x" prepend, but that crashes, saying it needs to be converted from a VARCHAR to a VARBINARY. When I convert it, the code runs and the column is populated, but the image is malformed.
No idea what to do next. Pls help.
Solution:
This is a basic approach using PHP Driver for SQL Server:
Table creation (T-SQL):
CREATE TABLE [dbo].[ImageTable] (
[ImageData] varbinary(max) NULL
)
PHP:
<?php
# Connection
$server = 'server\instance,port';
$database = 'database';
$uid = 'user';
$pwd = 'password';
$cinfo = array(
"Database" => $database,
"UID" => $uid,
"PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if( $conn === false )
{
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
# Update image using CONVERT()
$image = file_get_contents('image.jpg');
$sql = "UPDATE ImageTable SET [ImageData] = CONVERT(varbinary(max), ?) WHERE (yor_update_condition)";
$params = array(
array($image, SQLSRV_PARAM_IN)
);
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
# End
echo 'Image updated.'
?>
i have a problem to display the output of the stored procedure after success run the procedure...i hope everyone can help me....here my stored procedure..
$sql = "EXEC [dbo].[sp_mRetailerRegInfo_Add] '$var1','$var2','$var3','$var4','',''";
This my sample data in my SP
EXEC sp_mRetailerRegInfo_Add 'asdf','asdf','bacc#abc.com','123', #RetailerId output, #ErrorCode output
and this is my sample code ..i can run the procedure but it's not display the output
<?php
$serverName = "localhost";
$connectionInfo = array( "Database"=>"db", "UID"=>"user", "PWD"=>"pass");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn ) {
echo "Connection established.<br />";
}else{
echo "Connection could not be established.<br />";
die( print_r( sqlsrv_errors(), true));
}
//-----------------------------------------------
// Perform operations with connection.
//-----------------------------------------------
$sql = "EXEC [dbo].[sp_mRetailerRegInfo_Add] '$var1','$var2','$var3','$var4','',''";
$result = sqlsrv_query($conn, $sql);
if (!$result) {
echo 'Your code is fail.';
}
else {
echo 'Success!';
echo $result;
}
?>
the output will be like this (ID0001) and but i get the output like this
Connection established.
Success!Resource id #3
With a stored procedure, you would use an OUTPUT parameter that you would assign a value to within the procedure. When the procedure finishes, you would access that parameter and use the contents of it however you need.
You can read through Return Data from a Stored Procedure on the MSDN site to get an idea of how to write a stored procedure.
You will want to take a look at this already answered question that gives some details on how to access the OUTPUT parameter from PHP. You would want the second answer there:
The second param of execute needs to be true, rather than conn. This
should work:
$conn = mssql_connect('server', 'user', 'pass');
mssql_select_db('db', $conn);
$procedure = mssql_init('usp_StoredProc', $conn);
$tmpVar1 = 'value';
$tmpVar2 = 'value2';
$outVar1 = '';
$outVar2 = '';
mssql_bind($procedure, "#var1", $tmpVar1, SQLVARCHAR, false, false);
mssql_bind($procedure, "#var2", $tmpVar2, SQLVARCHAR, false, false);
mssql_bind($procedure, "#outVar1", $outVar1, SQLVARCHAR, true);
mssql_bind($procedure, "#outVar2", $outVar2, SQLVARCHAR, true);
mssql_execute($procedure,true);
print($outVar1);
print($outVar2);
If you could provide the definition for your stored procedure, I could elaborate more specifically on how to set up your PHP call.
Well, it's possible. There's a function called mssql_bind for binding the value to a PHP variable
To Call the SP and to store the Output. Try something like this
DECLARE #appout int; -- variable to hold the data returned by SP.
EXEC checkFollowing 10,20, #output = #appout OUTPUT; -- This is how i will call a SP.
#appout - will hold the data returned by the procedure.
So you can do execute your output parameter as below :
$outVar1 = '';
mssql_bind($procedure, "#appout", $outVar1, SQLVARCHAR, true);
mssql_execute($procedure,true);
print($outVar1);
So I have a PDO and MySQL script that is used to retrieve a result based on the user's username, or screen name, in this case being e.
First, I have a function at the beginning of the file that is used to connect to the database. (it is present in a functions.php file and required at the beginning of each page, thus the globalization). This function doesn't have anything wrong with it (as far as I know).
function SQLConnect () {
// Database connection variables
$host = "localhost";
$dbname = "dropbox";
$user = "root";
$password = "ethan17458";
// Connect to the database
try {
//put $connect in global scale of document
global $connect;
// attempt to connect to database
$connect = new PDO("mysql:host=$host;dbname=$dbname", $user, $password);
// Sets error mode
$connect->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch (PDOException $e) {
// Retrieves error message if connection fails
echo $e->getMessage();
}
}
This function uses PDO to connect to the database containing the user's information.
Next is the script to retrieve the user's data
// Test user in database
$test = "e";
try {
//confirms running of "try" block
echo "tried";
//database information
$host = "localhost";
$dbname = "dropbox";
$user = "root";
$password = "ethan17458";
//Prepare statement from connection function
// username_raw is "e"
//username should be e1671797c52e15f763380b45e841ec32 (md5)
$statement = $connect->prepare("SELECT `username` FROM `users` WHERE `username_raw` = ':name'");
//create placeholder for prepared statement
$statement->bindParam(":name", $test);
//make the statement fetch in an associative array
$statement->setFetchMode(PDO::FETCH_ASSOC);
//execute the prepared statement
$statement->execute();
//set $get_result to the fetched statement
$get_result = $statement->fetch();
//attempt to display the data fetched in $get_result
echo "<br />";
echo "<pre>";
//Outputs 1 for some reason
// **not working**
echo print_r($get_result);
echo "</pre>";
echo "<br />";
} catch (PDOException $e) {
//confirm running of "catch" block
echo "caught";
// echo error message
echo $e->getMessage();
}
When I run this script I get this output:
tried
1
In this output, tried is the confirmation that the "try" statement was processed, and the 1 is where I start to run into problems.
If the script was working as I would like, the script would retrieve the data e1671797c52e15f763380b45e841ec32 from the database because it is the column username where the username_raw is e, as is stated in the PDO prepared statement.
The ideal output should be
tried
e1671797c52e15f763380b45e841ec32
What am I doing wrong?
fetch() is returning false, which prints nothing to the screen. This is false because you're getting no results because you're putting single quotes around your parameter in the query, which PDO takes care of for you. Just remove the quotes around :name.