I've written a stored procedure ("UpdateTable") that takes one parameter and inserts a new row into a table when run.
I've got the following code in an asp page:-
dim conn
dim cmd
set conn = server.createobject("ADODB.Connection")
conn.open "Provider=SQLNCLI11;Data Source=(localdb)\Projects;Persist Security Info=False;Password=password;User ID=username;Initial Catalog=SQLLearning"
set cmd = server.createobject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "UpdateTable"
cmd.CommandType =adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("Text",adVarChar,adParamInput, 100)
cmd("Text") = "Jessica"
cmd.Execute
When I run this I get the following error:-
ADODB.Command error '800a0bb9'
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
/sp.asp, line 14
Where line 14 is the cmd.CommandType =adCmdStoredProc line. I've tried numerous things, including declaring a constant called adCmdStoredProc with the value of 4, and this still doesn't work. Can somebody please point me in the right direction?
The 'UpdateTable' code is:-
ALTER PROCEDURE UpdateTable
#Text varchar(100)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO StoredProcTest (Text)
OUTPUT inserted.ID, inserted.Text
VALUES (#Text)
END
GO
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "UpdateTable"
.Parameters.Append .CreateParameter("#Text",adVarChar,adParamInput, 100)
.Parameters("#Text") = "Jessica"
set rs = .Execute
End With
set cmd = nothing
You should then be able to get the result doing something similar to;
if not rs.eof then
response.write rs("ID")
end if
Related
Bit of an odd one here, essentially I have a VBA function in Microsoft Access that takes two arguments provided and cuts the data from the existing table to a temp table, and then compares this to the latest data from an external an SQL database and then reappends the updated information.
This has worked fine for years, and has never been touched, until recently, everytime I run the function I get an error:
Run-time error '-2147217904(8004e10)':
Too few parameters. Expected 2.
However, if I manually compact and repair, or recompile the database, this error goes away and the function completes as normal. But only for that session, currently the staff that use this function have to compact and repair everytime they open the Acces front end to make the function complete. Compact and repair on close does not work.
The code is below, but again, it has worked as-is for year with no changes and works after a C&R.
Function AccCompleteOrder(LabID As String, OrderID As String) As Boolean
Dim cmd As New ADODB.Command
Dim conn As New ADODB.Connection
Dim rstPackageCount As ADODB.Recordset
Dim rstTmpData As ADODB.Recordset
Dim rstRealData As New ADODB.Recordset
Dim i As Integer
Dim params() As Variant
'set up cmd and query parameters
params = Array(LabID, OrderID)
Set conn = CurrentProject.Connection
cmd.ActiveConnection = conn
'check that packages have been added to the order in genophyle
cmd.CommandText = "qryAccCheckPackagesAdded"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
Set rstPackageCount = cmd.Execute(, params)
If (rstPackageCount("packageCount") = 0) Then
AccCompleteOrder = False
Exit Function
End If
'Move dummy records to Temp table
If TableExists("tmpTblAccDeletion") Then
DoCmd.DeleteObject acTable, "tmpTblAccDeletion"
End If
cmd.CommandText = "qryAccMoveToTemp"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Execute , params
'delete old lines from table
cmd.CommandText = "qryAccDeleteFromWIL"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Execute , params
'Append real data from Genophyle orders
cmd.CommandText = "qryAccAppendfrmGenophyle"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Execute , params
'Get tempData recordset
cmd.CommandText = "qryAccSelectTmpData"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
Set rstTmpData = cmd.Execute
'Get real Data (from WIL) dataset
cmd.CommandText = "qryAccSelectRealData"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Parameters.Append cmd.CreateParameter("LabID", adChar, , 10, LabID)
cmd.Parameters.Append cmd.CreateParameter("OrderID", adBigInt, , 10, OrderID)
rstRealData.Open cmd, , adOpenDynamic, adLockOptimistic
Do While Not rstRealData.EOF
rstRealData("Country") = rstTmpData("Country")
Do While Not rstTmpData.EOF
If (rstRealData.Fields("Platform") = rstTmpData.Fields("Platform")) Then
For i = 0 To rstRealData.Fields.Count - 1
If (IsNull(rstRealData.Fields(i)) Or rstRealData.Fields(i) = 0) Then
rstRealData.Fields(i) = rstTmpData.Fields(i)
End If
Next
End If
rstTmpData.MoveNext
Loop
rstTmpData.MoveFirst
rstRealData.Update
rstRealData.MoveNext
Loop
rstRealData.Close
'update the accessioning check table
cmd.CommandText = "qryAccUpdateAccessioningCheckOrderComplete"
cmd.Parameters.Refresh
cmd.Parameters.Append cmd.CreateParameter("LabID", adChar, , 10, LabID)
cmd.Parameters.Append cmd.CreateParameter("OrderID", adBigInt, , 10, OrderID)
cmd.Parameters.Append cmd.CreateParameter("ComDate", adChar, , 50, Format(Now(), "dd/mm/yyyy hh:MM:ss"))
cmd.Parameters.Append cmd.CreateParameter("ComCheck", adBoolean, , , True)
cmd.Execute
AccCompleteOrder = True
End Function
The debugger indicates the error is when it reaches the line
rstRealData.Open cmd, , adOpenDynamic, adLockOptimistic
This has me stumped.
I have a simple table AMC_GW_TESTTABLE with two columns, name nvarchar(20) and phone nvarchar(12). I also have a simple stored procedure with two variables.
create procedure AMC_GW_TESTSP (#name nvarchar(20),
#phone nvarchar(12)) as
insert into AMC_GW_Testtable (name,phone)
values (#name, #Phone)
I have been able to get a button in Excel to create the command:
exec dbo.amc_gw_testsp 'fred' '620-555-1212'
But it does not execute it. I copy this to my SSMS exactly like it and execute it and it works fine. Any ideas?
VBA code
Sub Button1_Click()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim connStr As String
Dim param As ADODB.Parameter
Dim param2 As ADODB.Parameter
connStr = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;" _
& "Initial Catalog=am_app);Data Source=bcu-sql-01"
Set conn = New ADODB.Connection
conn.ConnectionString = connStr
conn.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "AMC_GW_TESTSP"
Set param = .CreateParameter("#name", adVarChar, adParamInput, 20, "Christopher")
.Parameters.Append param
Set param2 = .CreateParameter("#phone", adVarChar, adParamInput, 12, "0123456789")
.Parameters.Append param
.Execute
End With
conn.Close
Set cmd = Nothing
Set conn = Nothing
End Sub
I hope I did not scare you with a request for VBA Code
To give you an idea of what you should have:
Sub Button1_Click()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim connStr As String
Dim param As ADODB.Parameter
Dim param2 As ADODB.Parameter
connStr = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;" & _
"Initial Catalog=dbname;Data Source=servername"
Set conn = New ADODB.Connection
conn.ConnectionString = connStr
conn.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "AMC_GW_TESTSP"
Set param = .CreateParameter("#name", adVarChar, adParamInput, 20, "Christopher")
.Parameters.Append param
Set param2 = .CreateParameter("#phone", adVarChar, adParamInput, 12, "0123456789")
.Parameters.Append param
.Execute
End With
conn.Close
Set cmd = Nothing
Set conn = Nothing
End Sub
Things that you will have to change. Firstly the connection string (connStr). You will need to provide database name in place of dbname and server in place of servername. Also this string is assuming that you are using Windows Authentication for your SQL Server. If not you need to remove Integrated Security=SSPI; and in its place supply User ID=myUser;Password=myPassword;.
Next you will notice that the last parameter in the .CreateParameter function is a fixed string ("Christopher" and "0123456789"). In your case, they should be variables taken from cells in the spreadsheet. Please, please make sure that these strings do not contain ";" before trying to Execute.
I hope this helps, but feel free to contact me, if anything is less than clear!
PS You will need to make sure under Tools References, that you have the highest version of Microsoft ActiveX Data Objects Library checked (mine is 6.1, but anything 2.0 or higher definitely works).
I am trying to execute a SQL Server stored procedure from Excel VBA. The procedure returns rows into a result set object. However, while running the code, it throws an error:
3704 Operation is not allowed when the object is closed
Note:
There is no problem with the database connection because Select query running on the same connection object are working fine.
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter
Dim rst As New ADODB.Recordset
Set cn = New ADODB.Connection
Set cmd = New ADODB.Command
ThisWorkbook.initialize
cn.Provider = "sqloledb"
cn.Properties("Data Source").Value = ThisWorkbook.server
cn.Properties("Initial Catalog").Value = ThisWorkbook.db
cn.Properties("User ID").Value = "xxxxx"
cn.Properties("Password").Value = "xxxxx"
cn.Open
Set cmd = New ADODB.Command
cmd.CommandText = "Generate_KPI_Process_Quality_Check_RunTime"
cmd.CommandType = adCmdStoredProc
cmd.ActiveConnection = cn
Set prm = cmd.CreateParameter("#currentMonth", adChar, adParamInput, 255, cmb_month.Value)
cmd.Parameters.Append prm
Set prm = cmd.CreateParameter("#center", adChar, adParamInput, 255, cmb_center.Value)
cmd.Parameters.Append prm
rst.CursorType = adOpenStatic
rst.CursorLocation = adUseClient
rst.CursorLocation = adUseServer
rst.LockType = adLockOptimistic
rst.Open cmd
If (rst.BOF And rst.EOF) Then
'Some Code
End If
Put
SET NOCOUNT ON
in the stored procedure -- this will prevent output text generation like "1 record(s) updated".
You have to provide more parameters for the Open method of Recordset Object
try rst.Open cmd, cn
Use the Set keyword to assign the object:
Set cmd.ActiveConnection = cn
otherwise, the default property of the Connection object (which happen to be the connection string) will be assigned in lieu of the Connection object itself.
Just put another recordset that will contain resultsets
Dim rst1 As New ADODB.Recordset
SET rst1=rst.NextRecordset 'this will return the first resultset
If rst1.BOF or rst1.EOF Then...
'some code
End If
I have excel VBA script:
Set cоnn = CreateObject("ADODB.Connection")
conn.Open "report"
Set rs = conn.Execute("select * from table" )
Script work fine, but i want to add parameter to it. For example " where (parentid = myparam)", where myparam setted outside query string. How can i do it?
Of course i can modify query string, but i think it not very wise.
You need to use an ADODB.Command object that you can add parameters to. Here's basically what that looks like
Sub adotest()
Dim Cn As ADODB.Connection
Dim Cm As ADODB.Command
Dim Pm As ADODB.Parameter
Dim Rs as ADODB.Recordset
Set Cn = New ADODB.Connection
Cn.Open "mystring"
Set Cm = New ADODB.Command
With Cm
.ActiveConnection = Cn
.CommandText = "SELECT * FROM table WHERE parentid=?;"
.CommandType = adCmdText
Set Pm = .CreateParameter("parentid", adNumeric, adParamInput)
Pm.Value = 1
.Parameters.Append Pm
Set Rs = .Execute
End With
End Sub
The question mark in the CommandText is the placeholder for the parameter. I believe, but I'm not positive, that the order you Append parameters must match the order of the questions marks (when you have more than one). Don't be fooled that the parameter is named "parentid" because I don't think ADO cares about the name other than for identification.
Alternative example returning a command from a function:
Function BuildCommand(conn As ADODB.Connection) As ADODB.Command
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
cmd.Parameters.Append cmd.CreateParameter("#name", adVarChar, adParamInput, 255, "Dave")
cmd.CommandText = "SELECT * FROM users WHERE name = #name;"
Set BuildCommand = cmd
End Function
A couple things to note:
When using adVarChar data type, the size argument to cmd.CreateParameter (e.g. 255) is required. Not supplying it results a run-time error 3708: Application-defined or object-defined error, as indicated in the documentation:
If you specify a variable-length data type in the Type argument, you must either pass a Size argument or set the Size property of the Parameter object before appending it to the Parameters collection; otherwise, an error occurs.
If the cmd.ActiveConnection property is set when cmd.CommandText is set, and cmd.CommandText contains named parameters, cmd.Parameters will be populated accordingly. Calling cmd.Parameters.Append afterwards could result in duplicates. For example:
cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
Debug.Print cmd.Parameters.Count ' 0
cmd.CommandText = "SELECT * FROM users WHERE name = #name;"
Debug.Print cmd.Parameters.Count ' 1
cmd.Parameters.Append cmd.CreateParameter("#name", adVarChar, adParamInput, 255, "Dave")
Debug.Print cmd.Parameters.Count ' 2
I believe this is what is meant in the documentation, which is slightly inaccurate:
If the Prepared property of the Command object is set to True and the Command object is bound to an open connection when you set the CommandText property, ADO prepares the query (that is, a compiled form of the query that is stored by the provider) when you call the Execute or Open methods.
As a workaround, either set cmd.CommandText or cmd.ActiveConnection after adding parameters.
I am trying to pass #intDocumentNo and #intCustomerNo to a stored procedure using VBA but only #intCustomerNo is updated in dbo.tblOrderHead. I don't think the problem is with the procedure because if I enter the values manually it runs properly.
What am I doing wrong?
VBA Code:
Private Sub intCustomerNo_Click()
Dim cmdCommand As New ADODB.Command
With cmdCommand
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdStoredProc
.CommandText = "uspSelectCustomer"
'#intDocumentNo
.Parameters("#intDocumentNo").Value = Forms![frmSalesOrder].[IntOrderNo]
'#intCustomerNo
.Parameters("#intCustomerNo").Value = Me![intCustomerNo]
.Execute
End With
DoCmd.Close
Forms![frmSalesOrder].Requery
End Sub
Procedure:
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intCustomerNo = #intCustomerNo ,
dbo.tblOrderHead.intPaymentCode = dbo.tblCustomer.intPaymentCode,
dbo.tblOrderHead.txtDeliveryCode = dbo.tblCustomer.txtDeliveryCode,
dbo.tblOrderHead.txtRegionCode = dbo.tblCustomer.txtRegionCode,
dbo.tblOrderHead.txtCurrencyCode = dbo.tblCustomer.txtCurrencyCode,
dbo.tblOrderHead.txtLanguageCode = dbo.tblCustomer.txtLanguageCode
FROM dbo.tblOrderHead
INNER JOIN dbo.tblCustomer ON dbo.tblOrderHead.intCustomerNo =
dbo.tblCustomer.intCustomerNo
AND dbo.tblOrderHead.intOrderNo = #intDocumentNo
Solution
Change the procedure to this (suggestion below might work as well, but I have not yet tested):
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intCustomerNo = #intCustomerNo
WHERE dbo.tblOrderHead.intOrderNo = #intDocumentNo;
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intPaymentCode = dbo.tblCustomer.intPaymentCode,
dbo.tblOrderHead.txtDeliveryCode = dbo.tblCustomer.txtDeliveryCode,
dbo.tblOrderHead.txtRegionCode = dbo.tblCustomer.txtRegionCode,
dbo.tblOrderHead.txtCurrencyCode = dbo.tblCustomer.txtCurrencyCode,
dbo.tblOrderHead.txtLanguageCode = dbo.tblCustomer.txtLanguageCode
FROM dbo.tblOrderHead
INNER JOIN dbo.tblCustomer ON dbo.tblOrderHead.intCustomerNo =
dbo.tblCustomer.intCustomerNo
AND dbo.tblOrderHead.intOrderNo = #intDocumentNo
Try using SET NOCOUNT OFF in your SQL sp.
When an update or insert runs, it returns information on the amount of rows affected (like when you run in SSMS).
When an adodb.command recieves this information it stops executing, hence only executing your first statement.
You could try creating Parameter objects, then appending them to the Parameters collection.
The following is untested.
Private Sub intCustomerNo_Click()
Dim cmdCommand As New ADODB.Command
Dim paramDocNo as ADODB.Parameter
Dim paramCustNo as ADODB.Parameter
Set paramDocNo = cmdCommand.CreateParameter("#intDocumentNo", adInteger, adParamInput)
Set paramCustNo = cmdCommand.CreateParameter("#intCustomerNo", adInteger, adParamInput)
cmdCommand.Parameters.Append paramDocNo
cmdCommand.Parameters.Append paramCustNo
paramDocNo.Value = Forms![frmSalesOrder].[IntOrderNo]
paramCustNo.Value = Me![intCustomerNo]
With cmdCommand
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdStoredProc
.CommandText = "uspSelectCustomer"
.Execute
End With
DoCmd.Close
Forms![frmSalesOrder].Requery
End Sub
Could it possibly but you not declaring the parameters and it using an old cached copy? Personally when I issue parameters I use something like this. I’m not saying that is what is causing the problem but try it this way and see if it helps
Set cmd = New ADODB.Command
With cmd
.CommandText = "sptblTest_answers_UPSERT"
.CommandType = adCmdStoredProc
.ActiveConnection = dbCon
.Parameters.Append .CreateParameter("#Answer_ID", adInteger, adParamInput, , Me.txtAnswer_ID)
.Parameters.Append .CreateParameter("#Question_ID", adInteger, adParamInput, , Me.txtQuestion_ID)
.Parameters.Append .CreateParameter("#Answer_number", adTinyInt, adParamInput, , Me.txtAnswer_number)
.Execute
End with