PercyMedlem sedan mars 2000187 inlägg hej, har ett problem med att skapa en transaktion.
har förljande kod just nu:
strSQL = "begin tran "
strSQL = strSQL & "INSERT INTO OrderHead (OrderNo, CustomerId, DeliverySurname, Ip) VALUES (" & OrderNo & ", " & CustomerId & ", '" & DeliverySurname & "', '" & Request.ServerVariables("REMOTE_ADDR") & "') "
strSQL = strSQL & "select @@identity "
strSQL = strSQL & "commit tran"
Set ObjRs = Connection.Execute(strSQL)
OrderId = ObjRs(0)
får då felmeddelandet:
ADODB.Recordset error '800a0cc1'
Item cannot be found in the collection corresponding to the requested name or ordinal.
/AddOrder.asp, line 65
rad 65 är:
OrderId = ObjRs(0)
LarsG eller någon annan, vad är det för fel? hur skall det se ut för att få transaktionen att fungera? det jag vill är att få redan på id:t som skapades vid inserten.
tack på förhand
LarsGMedlem sedan dec. 200012 464 inlägg Det har inget med transaktioner att göra. Med din kod så kommer insert att returnera ett tomt recordset och det är det du får tillbaka vid execute. Resultatet av select-frågan kommer i ett annat recordset som du kan få tag på genom att göra
set objrs = objrs.nextrecordset()
Men om du däremot lägger till
strSQL = "begin tran [b]SET NOCOUNT ON[/b] "
strSQL = strSQL & "INSERT INTO OrderHead (OrderNo, CustomerId, DeliverySurname, Ip) " &_
"VALUES (" & OrderNo & ", " & CustomerId & ", '" & DeliverySurname & "', '" & _
Request.ServerVariables("REMOTE_ADDR") & "') "
strSQL = strSQL & "select @@identity "
strSQL = strSQL & "commit tran"
så kommer insert inte att ge upphov till ett recordset.
PercyMedlem sedan mars 2000187 inlägg tack LarsG, funkade utmärkt med det sista alt.
nu har jag dock en annan fråga. kan man få in hela nedanstående kod i en transaktion så att ingen annan kan komma och göra inlägg emellan (även om sannolikheten att någon skulle göra det precis mellan två frågor är väldigt liten)
strSQL = "begin tran set nocount on "
strSQL = strSQL & "INSERT INTO OrderHead (OrderNo, CustomerId, DeliverySurname, Ip) VALUES (" & OrderNo & ", " & CustomerId & ", '" & DeliverySurname & "', '" & Request.ServerVariables("REMOTE_ADDR") & "') "
strSQL = strSQL & "select @@identity "
strSQL = strSQL & "commit tran"
Set ObjRs = Connection.Execute(strSQL)
OrderId = ObjRs(0)
strSQL = "SELECT Article.Price, Temporder.ArticleId, Temporder.Amount FROM Article INNER JOIN Temporder ON Temporder.ArticleId = Article.ArticleId WHERE SessionId = " & Request.Cookies("SessionId")
Set rs = Connection.Execute(strSQL)
Do until rs.eof
'lägg till orderrader
strSQL = "INSERT INTO OrderItem (OrderId, ArticleId, Amount, Price) VALUES (" & OrderId & ", " & rs("ArticleId") & ", " & rs("Amount") & ", " & rs("Price") & ")"
Connection.Execute(strSQL)
rs.MoveNext
Loop
rs.Close
'tömmer temporära varukorgen
strSQL = "DELETE FROM Temporder WHERE SessionId = " & Request.Cookies("SessionId")
Connection.Execute(strSQL)
kan man få in den sista select frågan och efterfäljande loop i transaktionen?
LarsGMedlem sedan dec. 200012 464 inlägg Om du vill sköta allt från ASP så är det nog bättre att använda metoderna begintrans/committrans istället. Din loop där du flyttar data mellan tabeller går att skriva som ett statement med insert ... select
connection.begintrans()
strSQL = "set nocount on "
strSQL = strSQL & "INSERT INTO OrderHead (OrderNo, CustomerId, DeliverySurname, Ip) VALUES (" &_
OrderNo & ", " & CustomerId & ", '" & DeliverySurname & "', '" & Request.ServerVariables("REMOTE_ADDR") & "') "
strSQL = strSQL & "select @@identity "
Set ObjRs = Connection.Execute(strSQL)
strSQL = strSQL & insert into OrderItem SELECT Article.Price, Temporder.ArticleId, Temporder.Amount FROM " &_
" Article INNER JOIN Temporder ON Temporder.ArticleId = Article.ArticleId " &_
" WHERE SessionId = " & Request.Cookies("SessionId")
strSQL = strSQL & " DELETE FROM Temporder WHERE SessionId = " & Request.Cookies("SessionId") & " commit tran"
connection.execute strSQL
connect.committrans()
Du behöver lägga till lite felhantering så att du kan göra rollback om någon operation misslyckas.
Jag skulle nog lägga den här koden i en stored procedure istället.
PercyMedlem sedan mars 2000187 inlägg tack!
som koden är nu behövs det ingen loop för att lägga in flera poster?:
strSQL = strSQL & insert into OrderItem SELECT Article.Price, Temporder.ArticleId, Temporder.Amount FROM " &_
" Article INNER JOIN Temporder ON Temporder.ArticleId = Article.ArticleId " &_
" WHERE SessionId = " & Request.Cookies("SessionId")
lr den kanske klarar att lägga in fler poster utan att ha en loop?
tanken är att jag ska lägga den i en SP sen. kan dock inte ngt om det ännu...
men hur skulle koden för en SP se ut i så fall?
LarsGMedlem sedan dec. 200012 464 inlägg Nej, det behövs ingen loop.
Om man skulle göra om det till en stored procedure
create procedure percyFirst(
@orderNo int,
@customerId int,
@deliverySurname varchar(40),
@sessionId int,
@ip varchar(40))
as
declare @newId int,@errCode int
set nocount on
INSERT INTO OrderHead (OrderNo, CustomerId, DeliverySurname, Ip)
VALUES (@OrderNo,@CustomerId,@DeliverySurname ,@ip)
select @newid = @@identity,@errCode = @@error
if @errCode <> 0 goto panic
insert into OrderItem
SELECT Article.Price,
Temporder.ArticleId,
Temporder.Amount
FROM Article INNER JOIN Temporder
ON Temporder.ArticleId = Article.ArticleId
WHERE SessionId = @SessionId
select @errCode = @@error
if @errCode <> goto panic
DELETE FROM Temporder
WHERE SessionId = @SessionId
select 0,@newid
return
panic:
select @errCode,0
För att anropa en procedur så använder man kommandot
connect.begintrans()
set rs = connect.execute("execute percyFirst parameter,parameter2,...")
if rs(0) <> 0 then
connect.rollbacktrans()
else
connect.committrans()
end if
Tanken är att du får tillbaka ett recordset som innehåller dels en returkod och dels det nya räknarvärdet. Om returkoden <> 0 så får du göra rollback i ditt ASP program.
Mer om stored procedures
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_ca-co_5t9v.asp
PercyMedlem sedan mars 2000187 inlägg du är en hjälte LarsG :- )
tack, skall se ifall detta fungerar nu...