(PHP 4, PHP 5, PECL odbtp >= 1.1.1)

mssql_queryWysyła zapytanie do serwera MS SQL


Ta funkcja została USUNIĘTA w PHP 7.0.0.

Alernatywy dla tej funkcji obejmują:


mssql_query ( string $zapytanie [, resource $identyfikator_połączenia [, int $ograniczenie_liczby_wyników ]] ) : mixed

mssql_query() wysyła zapytanie do aktywnej bazy danych, na serwerze skojarzonym za pomocą identyfikatora połączenia.



Zapytanie SQL.


Identyfikator połączenia z MS SQL, zwrócony przez mssql_connect() lub mssql_pconnect().

Jeśli nie podano identyfikatora połączenia, przyjmowane jest ostatnio otwarte połączenie. Jeśli połączenie nie jest otwarte, funkcja próbuje nawiązać nowe i go użyć, tak jakby została wywołana mssql_connect().


Maksymalna liczba rekordów, które mają zostać umieszczone w buforze wynikowym.

Zwracane wartości

Zwraca identyfikator zbioru wynikowego, TRUE jeśli nie zostały zwrócone wiersze lub FALSE kiedy wystąpił błąd.


Przykład #1 Przykład mssql_query()

// Połączenie do MSSQL
$link mssql_connect('KALLESPC\SQLEXPRESS''sa''phpfi');

if (!
$link || !mssql_select_db('php'$link)) {
'Nie można nawiązać połączenia lub wybrać bazy danych!');

// Wykonaj proste zapytanie, pobierz wersję
// MSSQL i ją wyświetl.
$version mssql_query('SELECT @@VERSION');
$row mssql_fetch_array($version);


// Zwolnienie zasobów serwera zajmowanych przez zbiór wynikowy



Jeśli zapytanie zwraca wiele wyników, wówczas konieczne jest pobranie ich wszystkich za pomocą mssql_next_result() lub też zwolnienie za pomocą mssql_free_result() przed wykonaniem następnego zapytania.

Zobacz też:

add a note add a note

User Contributed Notes 33 notes

thewiglaf at gmail dot com
11 years ago
Note that although the documentations states that mssql_query will return "TRUE if no rows were returned", it will still return an empty resource identifier for SELECT statements that do not return any rows. This empty resource identifier will get dynamically typed as TRUE in a boolean context. Only for queries that do not actually return rows (eg. insert, update, or delete) will mssql_query return an actual boolean TRUE value.

We should use mssql_num_rows($resource) rather than $resource===TRUE for checking whether rows were returned.
sreekumar kv
10 years ago
If text fields from mssql SELECT queries are truncated (at 4096 characters), even after using ,
( 'mssql.textlimit' , '65536' );
ini_set ( 'mssql.textsize' , '65536' );

make sure that the ini_set function is used before the connection to the database is established.
8 years ago
In some cases when mssql_query() returns rows containing fields of type SMALLDATETIME or TIMESTAMP when the data is not NULL, PHP seems to enter some kind of error state where PHP no longer outputs anything to the browser. Not even data echoed before the query! DATETIME fields seem to work without this problem though.

When this happens, PHP doesn't give any errors even with error_reporting(-1), and no errors appear in Apache logfiles either.

There seems to be a workaround by explicitly calling flush() at the end of the skript.

In my case the problem occurred only when using some basic comparison operators for integer or string fields in a WHERE clause (eg. "WHERE id = 1000").

I discovered this behaviour on Ubuntu 11.10 (Linux 3.0.0-13-generic-pae), Apache 2.2.20, PHP 5.3.6-13ubuntu3.3 with Suhosin-Patch as Apache module, php5-mssql package using freetds
10 years ago
Regarding the problems mentioned on here with the format that datetime columns are returned in. Running on debian lenny and used apt-get install php5-sybase to get access to these functions. After which datetime fields were returned as a string something like 'Feb 16 2010 09:14:10:010AM' which was not recognised when passed to e.g. new DateTime(). Also smalldatetime fields caused php to crash.

To fix I did this:

vi /etc/php5/apache2/php.ini
After this line:
;mssql.datetimeconvert = On
Add this line:
mssql.datetimeconvert = Off

Now both datetime and smalldatetime come back as something like '2010-02-16 09:14:00'.
vollmer at ampache dot org
13 years ago
You need to escape ' with '' in mssql, however while doing a large dataset migration I ran into an issue with \0 (NULL) in the strings breaking the query. I ended up writting the below small little function, I'm sure it could be done faster/better but it has served me well.

function sqlEscape($sql) {

/* De MagicQuotes */
$fix_str        = stripslashes($sql);
$fix_str    = str_replace("'","''",$sql);
$fix_str     = str_replace("\0","[NULL]",$fix_str);


// sqlEscape
jagos at ebrno dot net
16 years ago
This's note about mssql and truncating binary output from database (mostly image ...), i spent about 2 days tuning this stuff and fortunately i made the hit ...
    so if you're experiencing truncates of your binary data read from mssql database (it looks like incomplete, broken or even no images) check mssql section of your php.ini file and set values of mssql.textlimit and mssql.textsize variables to their maximum (2147483647) or at least bigger size than the default is ... so i hope it helps a bit, have a good time
arnarb at oddi dot is
17 years ago
If you'd like to store binary data, such as an image, in MSSQL, it's common to have problems with addslashes and co.

This is because the MSSQL parser makes a clear distinction between binary an character constants. You can therefore not easilly insert binary data with "column = '$data'" syntax like in MySQL and others.

The MSSQL documentation states that binary constants should be represented by their unquoted hexadecimal byte-string. That is.. to set the binary column "col" to contain the bytes 0x12, 0x65 and 0x35 you shold do "col = 0x126535" in you query.

I've successfully stored and retrieved jpeg images in a column with the "image" datatype. Here's how:

// storing a file
$datastring = file_get_contents("img.jpg");
$data = unpack("H*hex", $datastring);
mssql_query("insert into images (name, data)
         values ('img.jpg', 0x".$data['hex'].")");

// retrieving
$result = mssql_query("select data from images where name = 'img.jpg'");
$row = mssql_fetch_assoc($result);
header("Content-type: image/jpeg;");
echo $row['data'];

As you can see there is nothing to do with the image on they way out, just blurb out the buffer your recieve as with any other field type.
jesse at lostangel dot net
17 years ago
While trying to return a @@IDENTITY after an INSERT statement, the only way I could get a valid return result was to encapsulate the query within an EXEC like so:

    $result = mssql_query("
        INSERT INTO Files
            (ownerId, name, sizeKB, path)
            VALUES ('$contactId', '$userfile_name', '$filesize', '$path')
        SELECT @@IDENTITY as fileId\")
    list($fileId) = mssql_fetch_row($result);

This returned the appropriate @@IDENTITY in a valid result set.  Not sure if mssql supports multiple inline commands or not.  But that assumption would back the useage of the EXEC command in order to execute these properly.
mikelasouris at yahoo dot com
12 years ago
Unicode data in a Unicode-only collation or ntext data cannot be sent to clients using DB-Library

try: select field from table, avoid "select * from table" php will scream at you. strangely after executing select field from table you'll be able to execute select * from table.

i'm using apache2, win XP, sqlexpress05
12 years ago
If you want to update a "text" field > 1,000 odd characters you must use WRITETEXT or UPDATETEXT.. how you ask:

function mssql_updatetext($db_name, $table_name, $field_name, $where, $text) {
    // assume mssql db link already created etc
    $buffer_len = 1024;
    mssql_query("EXEC sp_dboption '{$db_name}', 'select into/bulkcopy', 'true'");
    while ($str_pos < strlen($text)) {
        $buffer = str_replace("'", "''", substr($text, $str_pos, $buffer_len)); // escape buffer
        mssql_query("DECLARE @ptrval binary(16)

                     SELECT  @ptrval = TEXTPTR($field)
                     FROM    [$table]
                     WHERE   $where

                     UPDATETEXT [{$table}].$field @ptrval $str_pos NULL $buffer");
        $str_pos += $buffer_len;
    mssql_query("EXEC sp_dboption '$db_name', 'select into/bulkcopy', 'false'");
    return true;

// test it using "pubs" > pub_info.pr_info
    $where='pub_id = 9999',
    $text=str_repeat("This is a long bit of text \r\n", 1000)
8 years ago
Here are some things you might need to know:
1. Install mssql support for Debian (Lenny/Squeeze):
apt-get install php5-sybase

2. When you got this error message:
"Unicode data in a Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier."

In /etc/freetds/freetds.conf add these two lines (last two):
;tds version = 4.2
tds version = 8.0
client charset = UTF-8

You can edit "charset" in php.ini too (but you don't need if you did it previously in freetds.conf):
; Specify client character set..
; If empty or not set the client charset from freetds.comf is used
; This is only used when compiled with FreeTDS
mssql.charset = "UTF-8"

3. Use nchar/nvarchar/ntext column types if you need unicode support.
muratyaman at gmail dot com
13 years ago
It is annoying that MSSQL does not return proper error numbers.

For example: run a simple "INSERT INTO ..." query that will cause an error and see it.

All I get is:

Code:       HY000
Message: (below)

SQLSTATE[HY000]: General error: 10007 INSERT statement conflicted with COLUMN FOREIGN KEY constraint 'FK...'. The conflict occurred in database 'DB...', table 'TBL...', column 'COL...'. [10007] (severity 5) [INSERT INTO ... ]

'HY000' does not help me at all and same thing is returned for other errors as well. (I am not sure, but if 10007 is the number I am looking for, I do NOT want to parse the error messages. Then why do we have the notion of "err_code and err_message"?)

I think, running the following just after the 'failed' query may help:

$err = your_query_and_fetch_row_func ('select @@error');


P.S. Firebird rocks! ;)
km at mcminndigital dot com
14 years ago
Another note for the archives:

If for some reason you aren't on a windows platform (using FreeTDS etc), or on a older windows platform and are having a hard time with unicode errors with ntext and images there are two things to do:

1) make sure you odbc drivers are up to date
:: or ::
2) make sure to convert any ntext or image fields in your select. If you need an image from a select then you are stuck with upgrading your odbc drivers if you are getting unicode errors.

Use mssql_field_type to get your field types however you want.

SELECT [Name], [UserID], [SomeValue], convert(TEXT, [Description]) FROM [MyDB.[dbo].[MyTable];
andrei_mole at yahoo dot com
14 years ago
if anyone has faced a problem with displaying images from mssql image field it could be that they have an ole header put by sql.
here is an example. hope it helps:

$d=mssql_select_db("NorthWind", $db);
$sql = "SELECT Picture FROM Categories WHERE CategoryId=2";
$res = mssql_query($sql);
$row = mssql_fetch_array($res);
$data = $row['Picture'];
header("Content-Type: image/bmp");
//remove the ole header
$data = substr($data,78);
//print the pic in the browser
echo $data;
augustinus at netsession dot net
14 years ago
Regarding the note of jesse at lostangel dot net, written on 17-Sep-2002 03:33 implementing the mysql_insert_id function for MSSQL I have a remark:

The example hasn't worked on my database server (SQL Server 2000 Standard Edition with SP3a, english) so i just left of the exec statement.
Instead I used:

$result = mssql_query("INSERT INTO STUFF(gaga,otherGaga) VALUES ('hello','apple'); SELECT @@IDENTITY as insertId;");

list ($gagaId) = mssql_fetch_row($result);
Rizwan Khan
14 years ago
MSSQL will not let you use TEXT data in the where clause, TEXT data is BLOG data, its max size is 2,147,483,647 bytes (each character occupies one byte).
The varchar and char can have max of 8000 characters, so you can use text data in a where clause if you convert as follows convert(varchar(8000),SOMETEXTDATA)

select * from tHistory where myNotes=convert(varchar(8000),SOMETEXTDATA)
Rizwan Khan
14 years ago
Just explaining how to get date in YYYY-MM-DD format much easily, when you use convert function in SQL you usually give the format as one of the arguments. for example <br>
select convert(varchar(20),getdate(),20)<br>
select convert(varchar(20),getdate(),120)<br>
will both return dates in yyyy-mm-dd hh:mi:ss(24h) format. you can also use <br>
select convert(varchar(20),getdate(),21)<br>
select convert(varchar(20),getdate(),121)<br>
in yyyy-mm-dd hh:mi:ss.mmm(24h) formats.<br>
So now when you have the date as string from either of the four convert functions you can either take the left part of the string or use a substring function to get the date in YYYY-MM-DD format.<br>
following are few examples.<br>
select left(convert(varchar(20),getdate(),20),10)<br>
select left(convert(varchar(20),getdate(),120),10)<br>
select left(convert(varchar(20),getdate(),21),10)<br>
select left(convert(varchar(20),getdate(),121),10)<br>
select substring(convert(varchar(20),getdate(),20),1,10)<br>
select substring(convert(varchar(20),getdate(),20),1,10)<br>
select substring(convert(varchar(20),getdate(),120),1,10)<br>
select substring(convert(varchar(20),getdate(),21),1,10)<br>
select substring(convert(varchar(20),getdate(),121),1,10)<br>
tristanx3 at rogers dot com
14 years ago
It would appear that MSSQL will not let you use fields of the TEXT data type in WHERE clauses.

I tried running a simple query to get account data for a particular user based on email address, but the command was not returning any data.  I finally realized that this was because the emailaddress column was of the data type TEXT.  When I changed the WHERE clause in the query to test against a name, which was of type VARCHAR, the query worked perfectly.

I overcame this problem by converting the TEXT field to VARCHAR in the WHERE clause, as noted below:

### Field 'emailaddress' is of data type TEXT in the SQL database

# This would not work!
$sql = "SELECT * FROM accounts WHERE emailaddress = ''";

# Converting the data type inline solved the problem
$sql = "SELECT * FROM accounts WHERE CONVERT( VARCHAR, emailaddress ) = ''";

This seems to have solved my problem, although I am still unsure of the limits (if any) to this solution.
14 years ago
Another way how to use dates in queries:


$query = "
DECLARE @newdate datetime;
SELECT @newdate=convert(varchar(100), '$createdate', 102);

and fire the query....
php at syntax101 dot com
14 years ago
On certain server setups simply replacing a single quote with two single quotes will result in:

I use the following function for single quote escaping quote for MSsql:

function escapeSingleQuotes($string){
    //escapse single quotes
    $singQuotePattern = "'";
    $singQuoteReplace = "''";
    return(stripslashes(eregi_replace($singQuotePattern, $singQuoteReplace, $string)));
php at syntax101 dot com
14 years ago
On certain server setups simple replacing a single quote with two single quotes will result in:

I use the following function for single quote escaping quote for MSsql:

function escapeSingleQuotes($string){
    //escapse single quotes
    $singQuotePattern = "'";
    $singQuoteReplace = "''";
    return(stripslashes(eregi_replace($singQuotePattern, $singQuoteReplace, $string)));
rzachris at yahoo dot com
15 years ago
If you're having problems trying to get data stored in a varchar column with more than 255 chars use CONVERT to change the data type to TEXT like this:

$query=mssql_query("SELECT, CONVERT(TEXT, table.comment) AS comment FROM table");

Don't forget to set name for the column (AS comment) or you won't be able to retrieve the data ...
roger4a45 at yahoo dot es
15 years ago
Using Aplication Role with PHP


Aplication Role is a Microsoft SQL Server 2000 feature that allow to make control what "source" use your data. It means that you can allow select, inset or update operation from your PHP code and deny it from and ODBC source, Microsoft Access or any kind of application that want to use your data.


Imagina you have a DAtabase named MYDB. This DB has three table. TABLEA, TABLEB and TABLEC. Imagine that your user named 'nemesis' can access to TABLEA from anywhere but you want that from table B and C access from your PHP code.

Follow this steps

[From your MSSQL Administrator]

1 -. From your Database MYDB create a new role (Standard Role). Insert this user inside this role.
2 -. Edit permisions and deny any operation at TABLEB and TABLEC.
3 -. Create a new Role (Aplication Role). For intance  it named 'myaccess' with a password 'anypassword'.
4 -. Edit permisions and allow any operation you wish at TABLEB and TABLEC

[From your source] (I don't include any control errors to simplify source)

$s = mssql_connect('MYSERVER','nemesis','nemesispassword');
$b = mssql_select_db('MYDB',$s);

//This one activate application role. Any user permision are
//ignored. User permision are override with application role
// permisions.

$query = "EXEC sp_setapprole 'myaccess', 'anypassword'";
$b = mssql_query($query);
$result = mssql_query('SELECT * FROM TABLEB,$s);

Note: If you kill "$query = ..." you will find out that SELECT fails. If you insert that line $quey will be succeed. Now, nemesis only can take data from TABLEB and TABLEC through your PHP code. If he/She try to use that data through ODBC driver then he can not do it.

NOte: Application role drops when you make a mssql_close.
dennis at -nospam- darknoise d0t de
15 years ago
In response to post from jesse at lostangel dot net from 18-Sep-2002:

may NOT work as desired!
While running multiple queries at the same time, you will get the last identity value generated, somewhere in your database.

If you need to know the identity value generated by your INSERT statement, use SCOPE_IDENTITY().
16 years ago
You can run a stored proceedure AND get back a result set from mssql_query().  I figured this little trick out when I realized I couldn't use the mssql_init() function group for my stored procedure stuff as I needed datetime variables to be passed, and they are not supported.  However, you can "encapsulate" a snippet of stored procedure within a normal query that can be executed via mssql_query() and have a result value returned.  For example, here's a query which passes a store's local date and time to a stored procedure that converts it to the GMT values that is used internally by the rest of the database structure:
$storeid = 68;
$deptid = 70;
$StartDate = strftime("%b %d %Y %H:%M:%S",$temptime);
DECLARE @date datetime,
    @GMreturn datetime
SELECT @date='$StartDate'
execute TZ_toGMT '$storeid','$deptid',@date,@GMreturn OUTPUT
SELECT @GMreturn

Now, when $spquery is passed to mssql_query(), it will return with a value for @GMreturn, which can be parsed out with mssql_fetch_array() as with any other query.
papaggel at csd dot uoc dot gr
16 years ago
If you try to INSERT a large string to a MSSQLServer 2000 table attribute of type nvarchar/varchar/text/nchar/char, but it is limited to the first 256 characters do the following:

1. Open Tools->SQL Query Analyzer
2. In SQL Query Analyzer
    i.   Go to Tools->Options
    ii.  Select the "Results" tab
    iii. Change "Maximum characters per column" to something else
16 years ago
Kelsey made a note that the only character that MSSQL needs "escaping" is the single quote ', and it done by using two single quotes ''.  You will want to make sure that, when using strings, you contain the strings in single quotes, since you can't escape double quotes.

In addition, you won't find a mssql_escape_string() function (though there are for other DB's, i.e. mysql_escape_string()), but using:

$escapedString = str_replace("'","''",$stringToEscape);

Will accomplish the same thing.
17 years ago
If you are experiencing TRUNCATING issues trying to return more than 4096 bytes on a VARCHAR field try converting it to text:

CONVERT(TEXT, Yourfield)

$sql->db_select("SELECT cc_main.cc_entry_id, CONVERT(TEXT, cc_main.comment) FROM cc_main");
wind at wag dot nl
17 years ago
Had a similar problem to Jesse

What I experienced with Microsoft SQLserver 2000 and PHP 4.1.2 was that if you execute a query consisting of multiple queries separated by a semicolon with mssql_query is that the queries themselves are executed but the connection is dropped immediately after that. It seems that the phpdriver doesn't count on this.
The EXEC solution (or maybe sp_executesql) works fine in these cases because to the db-library it is one statement.
php at netznacht dot de
17 years ago
Just tried to give a string:

Welcome at Mike's   to the SQL Server:

He misinterpreted the \' as the end of the String.
MySQL will resolve  \' and not think that the String has ended.

You should replace the \' before constructing the MSSQL Query string.
cusaacb at squared dot com
18 years ago
Using the latest version of freetds with support for tds ver 7.0.  I could not get more than 256 characters on varchar until I set the environment variable TDSVER=70. 

Then it correctly returns all of the field.
arthur dot mcgibbon at btinternet dot com
18 years ago
The mssql_execute etc. commands for stored procs do not seem to support a DATETIME type.
This means using mssql_query.
Now problems occur when you want to use parameters that have Input values and Output values.  SQL Server refuses to acknowledge the following...

declare @ret int, @i int
select @i = 25
exec @ret = testsp @Param1 = @i output
select @ret, @i

It doesn't like 2 select statements, even when the first is changed to "set".

To get round this, put the whole query into an exec command.
mssql_query("exec('declare @ret int, @i int
select @i = 25
exec @ret = testsp @Param1 = @i output
select @ret, @i')"

This seems to work fine.
9 years ago
I had this problem upgrading to sqlsrv from mssql. In short, SCOPE_IDENTITY doesn't seem to work with sqlsrv correctly when using parameters. This isn't in fact the case, it just works differently.

To recap the problem:

Table 'test' definitely has an identity column id. However you can not do (apologies for pseudo-code):

("INSERT INTO test (col1, col2) VALUES (?,?)", $parameters);
$lastId=doquery("SELECT SCOPE_IDENTITY()");

because, under sqlsrv, these two queries are in different scopes, so there is nothing to return... However, this also doesn't work as expected:

= "INSERT INTO test (col1, col2) VALUES (?,?); SELECT SCOPE_IDENTITY()";
$resource=sqlsrv_query($conn, $query, $arrParams);
$arrRow = sqlsrv_fetch_array($resource, SQLSRV_FETCH_ASSOC);

Here you might expect to see the last insert id, but you see nothing. This is because the resource is currently pointing to the 'true' from the first query (the insert query) and so the insert id is 'hidden' in another row of the resource.

Solution.... set up as before, but then:

=sqlsrv_query($conn, $query, $arrParams);
sqlsrv_get_field($resource, 0);

This will give you what you want! This will work similarly with something like "INSERT INTO test (col1, col2) VALUES (?,?); SELECT * from test WHERE ID = SCOPE_IDENTITY()" and again you have to move through the resource to get at the data you want.

I hope this helps someone, since it's just wasted a good two hours of my time! Also, sorry for any errors in the code - I'm afraid I've written it off the top of my head, but hopefully you get the idea...
To Top