Home All Groups Group Topic Archive Search About

Transactions in PHP on SQL Server 2005

Author
15 Jul 2006 3:40 PM
~john
I'm trying to get a transaction to work with PHP 5.1.4 and SQL Server
2005... The first SQL statement deletes several rows in the database.
The next SQL statement loops through and inserts several rows into the
same table. What I'm wanting is for the database to rollback all
transactions if any 1 of the inserts fail. What's happening now is the
DELETE statement runs successfully deleting several rows... but as soon
as one of the INSERTS  fail, the page errors out WITHOUT rolling back
the DELETE statements. What am I doing wrong in my code?

thanks,

~john

mssql_query("BEGIN TRAN");

$sql = "DELETE FROM MyTable WHERE Value > 0";

$result = mssql_query($sql);

foreach(loopVar as val)
{
          $sql = "INSERT INTO MyTable VALUES(1)";
          $result = mssql_query($sql);

          if( ! $result ){
                mssql_query('ROLLBACK TRAN');
                exit;
          }

}                     

mssql_query("COMMIT TRAN");

Author
15 Jul 2006 4:10 PM
Norman Yuan
I do not know PHP, but it is obviously that how do you handle error in your
code: if error occurs during a transaction, your routine should continue to
run so that the kine of code calling "ROLLBACK TRAN" can be reached and
executed.

So, this line of code it where problem is:

$result = mssql_query($sql);

You have to make sure msssql_query() ALWAYS return something no matter what
happens. I do not know what the statement does behind the sceen, besides
executing the sql statement, but certainly the simple "INSERT INTO..." sql
statement does not do anything if the SQL Server fails the insertion. Unless
the PHP's mssql_query() method guarantees you that it always returns
something and never break, you have to handle the possible runtime exception
(I do believe PHP has some exception handling mechanism, does it?) to ensure
the ROLLBACK TRAN call can be executed if necessary.

I have to say, this has little to do with SQL Server itself.

Show quote
"~john" <SonVolt***@gmail.com> wrote in message
news:1152978014.550173.293830@35g2000cwc.googlegroups.com...
> I'm trying to get a transaction to work with PHP 5.1.4 and SQL Server
> 2005... The first SQL statement deletes several rows in the database.
> The next SQL statement loops through and inserts several rows into the
> same table. What I'm wanting is for the database to rollback all
> transactions if any 1 of the inserts fail. What's happening now is the
> DELETE statement runs successfully deleting several rows... but as soon
> as one of the INSERTS  fail, the page errors out WITHOUT rolling back
> the DELETE statements. What am I doing wrong in my code?
>
> thanks,
>
> ~john
>
> mssql_query("BEGIN TRAN");
>
> $sql = "DELETE FROM MyTable WHERE Value > 0";
>
> $result = mssql_query($sql);
>
> foreach(loopVar as val)
> {
>          $sql = "INSERT INTO MyTable VALUES(1)";
>          $result = mssql_query($sql);
>
>          if( ! $result ){
>                mssql_query('ROLLBACK TRAN');
>                exit;
>          }
>
> }
>
> mssql_query("COMMIT TRAN");
>
Author
15 Jul 2006 8:08 PM
Stu
In addition to Norman's suggestion, why are you not using stored
procedures to handle the transaction for you?  You minimize the
possibility of SQL injection becuase you'll be using parameters, and
you increase the likelihood of a performance gain, and you're avoiding
some of the pain of trying to manage transactions at the client level.

Of course, there are reasons to NOT use stored procedures, but you
didn't specify one, so I'm assuming that a stored proc is a aviable
option.

Stu

Norman Yuan wrote:
Show quote
> I do not know PHP, but it is obviously that how do you handle error in your
> code: if error occurs during a transaction, your routine should continue to
> run so that the kine of code calling "ROLLBACK TRAN" can be reached and
> executed.
>
> So, this line of code it where problem is:
>
> $result = mssql_query($sql);
>
> You have to make sure msssql_query() ALWAYS return something no matter what
> happens. I do not know what the statement does behind the sceen, besides
> executing the sql statement, but certainly the simple "INSERT INTO..." sql
> statement does not do anything if the SQL Server fails the insertion. Unless
> the PHP's mssql_query() method guarantees you that it always returns
> something and never break, you have to handle the possible runtime exception
> (I do believe PHP has some exception handling mechanism, does it?) to ensure
> the ROLLBACK TRAN call can be executed if necessary.
>
> I have to say, this has little to do with SQL Server itself.
>
> "~john" <SonVolt***@gmail.com> wrote in message
> news:1152978014.550173.293830@35g2000cwc.googlegroups.com...
> > I'm trying to get a transaction to work with PHP 5.1.4 and SQL Server
> > 2005... The first SQL statement deletes several rows in the database.
> > The next SQL statement loops through and inserts several rows into the
> > same table. What I'm wanting is for the database to rollback all
> > transactions if any 1 of the inserts fail. What's happening now is the
> > DELETE statement runs successfully deleting several rows... but as soon
> > as one of the INSERTS  fail, the page errors out WITHOUT rolling back
> > the DELETE statements. What am I doing wrong in my code?
> >
> > thanks,
> >
> > ~john
> >
> > mssql_query("BEGIN TRAN");
> >
> > $sql = "DELETE FROM MyTable WHERE Value > 0";
> >
> > $result = mssql_query($sql);
> >
> > foreach(loopVar as val)
> > {
> >          $sql = "INSERT INTO MyTable VALUES(1)";
> >          $result = mssql_query($sql);
> >
> >          if( ! $result ){
> >                mssql_query('ROLLBACK TRAN');
> >                exit;
> >          }
> >
> > }
> >
> > mssql_query("COMMIT TRAN");
> >
Author
15 Jul 2006 10:38 PM
~john
Stu wrote:
> In addition to Norman's suggestion, why are you not using stored
> procedures to handle the transaction for you?  You minimize the
> possibility of SQL injection becuase you'll be using parameters, and
> you increase the likelihood of a performance gain, and you're avoiding
> some of the pain of trying to manage transactions at the client level.


Well... yeah, I suppose it's an option but this is an applicatoin for a
corporate intranet cut off from the outside world so I'm not overly
concerned with SQL injection and what not. I've tried using stored
procs in the past but I found SQL programming to be combersome (what,
no arrays? :P).. maybe I'll give it another shot.

Let's say I do use a stored procedure... When I'm inserting multiple
rows inside the loop, how would I handle this in a stored proc? I'm
guessing you can't pass in an array to loop through your inserts, so
that leaves you just calling the stored proc from within my PHP code's
loop... if that's the case how would i handle the transaction since I
need a START and COMMIT before and after all the INSERTS and DELETES

~john
Author
16 Jul 2006 12:17 AM
Stu
~john wrote:
> Stu wrote:
> > In addition to Norman's suggestion, why are you not using stored
> > procedures to handle the transaction for you?  You minimize the
> > possibility of SQL injection becuase you'll be using parameters, and
> > you increase the likelihood of a performance gain, and you're avoiding
> > some of the pain of trying to manage transactions at the client level.
>
>
> Well... yeah, I suppose it's an option but this is an applicatoin for a
> corporate intranet cut off from the outside world so I'm not overly
> concerned with SQL injection and what not. I've tried using stored
> procs in the past but I found SQL programming to be combersome (what,
> no arrays? :P).. maybe I'll give it another shot.

Funny; I felt the same way about PHP :)  Iterations?

>
> Let's say I do use a stored procedure... When I'm inserting multiple
> rows inside the loop, how would I handle this in a stored proc? I'm
> guessing you can't pass in an array to loop through your inserts, so
> that leaves you just calling the stored proc from within my PHP code's
> loop... if that's the case how would i handle the transaction since I
> need a START and COMMIT before and after all the INSERTS and DELETES
>
> ~john

Actually, there are ways to emulate arrays in SQL; Erland has an
excellent page on this at http://www.sommarskog.se/arrays-in-sql.html.
Although he advocates NOT using OpenXML to emulate an array, I've used
this method before to pass in several rows at a time to be processed
within a single stored procedure.

Ultimately, though, it does come down to handling the transaction with
both a commit and a rollback, and unfortunately, I don't know enough
about PHP to help you much further than what you have already done.  It
does appear to me that you are not opening a transaction that
encompasses the commands following it; rather, you tell SQL Server to
Begin a Transaction, and then you return from it back to the client
layer which implicitly commits that transaction.

Does PHP use ADO to manage the connection to SQL Server?

Stu
Author
16 Jul 2006 10:07 PM
Erland Sommarskog
Stu (stuart.ainswo***@gmail.com) writes:
> Actually, there are ways to emulate arrays in SQL; Erland has an
> excellent page on this at http://www.sommarskog.se/arrays-in-sql.html.
> Although he advocates NOT using OpenXML to emulate an array, I've used
> this method before to pass in several rows at a time to be processed
> within a single stored procedure.

Nah, I would say that all if you need is a list of single values, then
XML is a bit of overkill.

But if you want to send down a set of rows for insertion, XML is indeed
the way to go.


--
Erland Sommarskog, SQL Server MVP, esq***@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
Author
16 Jul 2006 2:42 AM
Tracy McKibben
~john wrote:
Show quote
> Stu wrote:
>> In addition to Norman's suggestion, why are you not using stored
>> procedures to handle the transaction for you?  You minimize the
>> possibility of SQL injection becuase you'll be using parameters, and
>> you increase the likelihood of a performance gain, and you're avoiding
>> some of the pain of trying to manage transactions at the client level.
>
>
> Well... yeah, I suppose it's an option but this is an applicatoin for a
> corporate intranet cut off from the outside world so I'm not overly
> concerned with SQL injection and what not. I've tried using stored
> procs in the past but I found SQL programming to be combersome (what,
> no arrays? :P).. maybe I'll give it another shot.
>
> Let's say I do use a stored procedure... When I'm inserting multiple
> rows inside the loop, how would I handle this in a stored proc? I'm
> guessing you can't pass in an array to loop through your inserts, so
> that leaves you just calling the stored proc from within my PHP code's
> loop... if that's the case how would i handle the transaction since I
> need a START and COMMIT before and after all the INSERTS and DELETES
>
> ~john
>

You can pass a delimited string to a stored proc and then parse within
the proc:

http://realsqlguy.com/twiki/bin/view/RealSQLGuy/ParseDelimitedStringToTable



--
Tracy McKibben
MCDBA
http://www.realsqlguy.com
Author
16 Jul 2006 10:10 PM
Erland Sommarskog
~john (SonVolt***@gmail.com) writes:
> Well... yeah, I suppose it's an option but this is an applicatoin for a
> corporate intranet cut off from the outside world so I'm not overly
> concerned with SQL injection and what not.

There can be intruders on the inside as well. SQL Injection is something
you should consider in any application.

> I've tried using stored procs in the past but I found SQL programming to
> be combersome (what, no arrays?

No arrays? Sure there are, but they are called tables and are far more
general in nature than arrays.

> Let's say I do use a stored procedure... When I'm inserting multiple
> rows inside the loop, how would I handle this in a stored proc?

The simple-minded way would of course to be call the an SP to
insert one row. A more effective way is to form an XML document
and then have the procedure to unpack it with OPENXML and insert
all rows in one go.


--
Erland Sommarskog, SQL Server MVP, esq***@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx
Author
17 Jul 2006 10:35 PM
~john
***UPDATE***

Well, I'm not sure what I was smokin' the day I thought the
Transactions were not working... they do in fact appear to be working
as expected. Thanks everyone for all your help.

And Stu... I'm using PHP's Sql Server calls that come as an included
DLL with the PHP installation.

~john

AddThis Social Bookmark Button