I have an online form, data from there needs to be entered into a MSSQL database. I'm trying to create a secure insert statement. With the following code I get this error.
Microsoft OLE DB Provider for SQL Server error '80040e5d'
Parameter name is unrecognized.
<%#language="vbscript" codepage="65001" %>
<% option explicit %>
Dim Form_Name
Dim Form_Email
Form_Name= ProtectSQL(request.Form("Name"))
Form_Email= ProtectSQL(Request.Form("Email"))
Dim objConn
set objConn = Server.CreateObject("ADODB.Connection")
Dim strConn
strConn="provider=SQLOLEDB;Server=localhost;Database=dbname;Uid=username;Pwd=password;"
objConn.open strConn
Dim DateSubmitted
DateSubmitted=now()
Dim strSQL
strSQL = "INSERT INTO tablename(DateSubmitted, Name, Email) VALUES('" & DateSubmitted & "', ?, ?)"
Dim objCmd
set objCmd = Server.Createobject("ADODB.Command")
objCmd.ActiveConnection = objConn
objCmd.CommandText = strSQL
objCmd.CommandType = adCmdText
objCmd.NamedParameters = true
Dim objParam1
Set objParam1 = objCmd.CreateParameter("Name", adVarChar, adParamInput, Len(Form_Name), Form_Name)
objCmd.Parameters.Append objParam1
Dim objparam2
Set objparam2 = objCmd.CreateParameter("Email", adVarChar, adParamInput, Len(Form_Email), Form_Email)
objCmd.Parameters.Append objparam2
objCmd.Execute, , adCmdText And adExecuteNoRecords
objConn.close
Set objConn = Nothing
I have also tried
strSQL = "INSERT into tablename(DateSubmitted,Name,Email)values('" & DateSubmitted & "',#Name,#Email)"
objCmd.Parameters.Append objCmd.CreateParameter("#Name",adVarChar,adParamInput,100,Form_Name)
objCmd.Parameters.Append objCmd.CreateParameter("#Email",adVarChar,adParamInput,100,Form_Email)
With this I get Must declare the scalar variable "#Name".
Both error messages reference the objCmd.Execute line
Is there a better way to do an insert statement? I don't need a recordset with this.
You have 5 placeholders in
strSQL = "INSERT INTO tablename(DateSubmitted, Name, Email) VALUES('" & DateSubmitted & "', ?, ?, ?, ?, ?)"
but add only 2 parameters.
I use code like the following code to perform parameterized queries in classic asp:
public sub sql_execute(sql, parameterArray)
dim cnx
Set cnx=CreateObject("ADODB.Connection")
cnx.Open wfDataConnection
if isArray(parameterArray) then
dim cmd, i
Set cmd = CreateObject("ADODB.Command")
With cmd
.CommandText = sql
.CommandType = adCmdText
.ActiveConnection = cnx
for each i in parameterArray
.Parameters.Append .CreateParameter(i(0), i(1), i(2), i(3), i(4))
next
end with
cmd.execute rowsAffected, , adExecuteNoRecords
else
cnx.execute sql, rowsAffected, adExecuteNoRecords
end if
end sub
Calling it like so:
dim sql, parameterArray
sql = "INSERT INTO table (val1, val2) VALUES (?, ?)"
paramaterArray = Array(_
Array("#p1", adInteger, adParamInput, , val1)_
, Array("#p2", adVarChar, adParamInput, 255, val2)_
)
sql_execute sql, parameterArray
I'm not too sure about the variable names (#p1, #p2, etc) when creating parameters. It doesn't seem to matter what you call the variables, but they do require some kind of name in order for it to work.
Related
This is my stored procedure which works fine in SQL Server Management Studio.
exec GroupCommissions #GroupNumberEntry = '01142'
Should produce a table of data.
I'm trying to run it in vba using the following code:
Dim rs As ADODB.Recordset
Dim cnSQL As ADODB.Connection
Dim sqlcommand As ADODB.Command, prm As Object
Set cnSQL = New ADODB.Connection
cnSQL.Open "Provider=SQLOLEDB; Data Source=bddc1didw1;Initial Catalog=Actuarial; Trusted_connection=Yes; Integrated Security='SSPI'"
Set sqlcommand = New ADODB.Command
sqlcommand.ActiveConnection = cnSQL
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "GroupCommissions"
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adParamInput)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters("GroupNumberEntry").Value = "01142"
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
ActiveSheet.Range("a3").CopyFromRecordset rs
But it just returns blank and I can't work out what I'm doing wrong. Also is there a simpler way to do this?
As discussed below i've managed to fix the issue by adding SET NOCOUNT ON to the original stored procedure. My issue now is I want to do a second stored procedure in the same code but it only seems to work for one. They both work individually however. So either I have to reopen the connection or use 2 on the defined variables? Here is the code:
Dim rs As ADODB.Recordset
Dim cnSQL As ADODB.Connection
Dim sqlcommand As ADODB.Command, prm As Object, prm2 As Object
Set cnSQL = New ADODB.Connection
cnSQL.Open "Provider=SQLOLEDB; Data Source=bddc1didw1;Initial Catalog=Actuarial; Trusted_connection=Yes; Integrated Security='SSPI'"
Set sqlcommand = New ADODB.Command
sqlcommand.ActiveConnection = cnSQL
'groupdates
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "GroupDate"
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adVarChar, adParamInput, 5)
Set prm2 = sqlcommand.CreateParameter("ValuationDateEntry", adDate, adParamInput)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters.Append prm2
sqlcommand.Parameters("GroupNumberEntry").Value = "01132"
sqlcommand.Parameters("ValuationDateEntry").Value = "08-31-2019"
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
ActiveSheet.Range("a2").CopyFromRecordset rs
'GroupCommissions
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "GroupCommissions"
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adVarChar, adParamInput, 5)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters("GroupNumberEntry").Value = "01132"
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
ActiveSheet.Range("DB2").CopyFromRecordset rs
Try replacing that line with something like this:
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adVarChar, GroupNumberEntry, 255)
Set the field type and length according to how your proc is defined.
Your code looked OK to me so I copied it into Excel (2016...) and tried it. It gave me an error on that line but adding the additional parameter values to CreateParameter fixed the issue. shrug It shouldn't matter since those are optional parameters, unless there is something maybe at the provider level.
you can try just sending the SQL PROCEDURE straight through as a CALL function.
Take a look at this:
Public connDB As New ADODB.Connection
Public rs As New ADODB.Recordset
Public strSQL As String
Public strConnectionstring As String
Public strServer As String
Public strDBase As String
Public strUser As String
Public strPwd As String
Public PayrollDate As String
Sub WriteStoredProcedure()
PayrollDate = "2017/05/25"
Call ConnectDatabase
On Error GoTo errSP
strSQL = "EXEC spAgeRange '" & PayrollDate & "'"
connDB.Execute (strSQL)
Exit Sub
errSP:
MsgBox Err.Description
End Sub
Sub ConnectDatabase()
If connDB.State = 1 Then connDB.Close
On Error GoTo ErrConnect
strServer = "SERVERNAME" ‘The name or IP Address of the SQL Server
strDBase = "TestDB"
strUser = "" 'leave this blank for Windows authentication
strPwd = ""
If strPwd > "" Then
strConnectionstring = "DRIVER={SQL Server};Server=" & strServer & ";Database=" & strDBase & ";Uid=" & strUser & ";Pwd=" & strPwd & ";Connection Timeout=30;"
Else
strConnectionstring = "DRIVER={SQL Server};SERVER=" & strServer & ";Trusted_Connection=yes;DATABASE=" & strDBase 'Windows authentication
End If
connDB.ConnectionTimeout = 30
connDB.Open strConnectionstring
Exit Sub
ErrConnect:
MsgBox Err.Description
End Sub
I'm making a program in which I have to check some column values in another table before trying to save values in a different table.. both tables are in SQL.
I tried my best to do it myself but I get the error near the highlighted line.
rs.open(insert into testreport_tb1...
Private Sub Command1_Click()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim BrdSrNo As String
Dim Result As Boolean
Dim machineName As String
machineName = Environ("computername")
' Ready objects for use.
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
BrdSrNo = BoardSrNo.Text
Result = False
' Connect.
cn.Open "{Here I give the connection string}"
' Fetch a recordset.
rs.Open "select * from testreport_tb1 where board_SrNo = '" & BrdSrNo & "' order by test_DateTime desc", cn, adOpenStatic, adLockReadOnly
' Display value, and total recordcount.
MsgBox rs.Fields(3)
MsgBox rs.Fields(8)
'MsgBox rs.RecordCount
stage_Status = rs.Fields(3)
stage_Id = rs.Fields(8)
rs.Close
cn.Close
If stage_Status = "C" Then
If stage_Id = "True" Then
rs.Open "insert into testreport_tb1 values('" & BrdSrNo & "',3,GETDATE(),'" & Result & "',NULL,'" & machineName & "',' KO ','A','D')", cn, adOpenDynamic, adLockBatchOptimistic
MsgBox "saved"
End If
End If
' Close and release objects.
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
As far as I remember, you can't use rs.Open when executing DML statements, (insert, update or delete), but only when you are executing select statements.
Also, you need to use ADODB.Command and set parameters instead of concatenating strings to create your insert statement, otherwise it's an open door for sql injection attacks.
It's been a very long time since the last time I've worked with ADODB, but your insert code should look something like this:
If stage_Status = "C" And stage_Id = "True" Then
Dim cmd as new ADODB.Command
cmd.CommandText = "insert into testreport_tb1 values(?, 3, GETDATE(), ?, NULL, ?, ' KO ', 'A', 'D')"
cmd.ActiveConnection = cn
Set param = cmd.CreateParameter(, adVarChar, adParamInput)
param.Value = BrdSrNo
cmd.Parameters.Append param
Set param = cmd.CreateParameter(, adVarChar, adParamInput)
param.Value = Result
cmd.Parameters.Append param
Set param = cmd.CreateParameter(, adVarChar, adParamInput)
param.Value = machineName
cmd.Parameters.Append param
cmd.Execute
MsgBox "saved"
End If
Note: Code was written directly here, and as I wrote, it's been a long time since I've used ADODB, so there might be mistakes in the code. However, this is the proper way of executing an insert statement with ADODB.
I am trying to debug Excel VBA code that is calling a stored procedure resident on our SQL Server (SQL Server 2008 R2). With a bit of error trapping I can now see what the error is but I have no idea what is causing it.
Here is my VBA code:
Sub Add_Results_Of_ADO_Recordset()
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Dim cmd As ADODB.Command
Dim stSQL As String
Const stADO As String = "Provider=SQLOLEDB.1;User ID =xxxxx;Password=xxxxx;" & _
"Persist Security Info=False;" & _
"Initial Catalog=MyDatabase;" & _
"Data Source=xxxxxxxxxxxx"
' initialise ADO
Set cnt = New ADODB.Connection
cnt.Open stADO
On Error GoTo Err_SaveProposal
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = cnt
.CommandText = "PolicyList"
.CommandType = adCmdStoredProc
.NamedParameters = True
.Parameters.Refresh
.Parameters.Append .CreateParameter("#Incept", adVarChar, adParamInput, 10, "2/1/2014")
.Parameters.Append .CreateParameter("#Expire", adVarChar, adParamInput, 10, "2/1/2014")
.Parameters.Append .CreateParameter("#PStatus", adVarChar, adParamInput, 20, "BOOK")
End With
' Debug code to ensure parameters are set correctly
For Each prm In cmd.Parameters
Debug.Print prm.Name & " : " & prm.Value
Next
cmd.Execute
If cnt.State = adStateOpen Then cnt.Close
Exit Sub
Err_SaveProposal:
Debug.Print Err.Number & ": " & Err.Description
If cnt.State = adStateOpen Then cnt.Close
End Sub
Here are the messages written to the immediate window:
#RETURN_VALUE :
#Incept :
#Expire :
#PStatus :
#Incept : 2/1/2014
#Expire : 2/1/2014
#PStatus : BOOK
-2147217900: Procedure or function PolicyList has too many arguments specified.
It looks like the three arguments I am trying to send to the stored procedure are being sent twice. Once as empty strings and one with the values I want to send. Any suggestions?
I've set up a Stored Procedure in SQL Server that works fine. I can now call it from VBA, but want to return a value to know if there were any errors etc. The last parameter in my SP is set up as OUTPUT:
#DataSetID int = 0,
#Destination char(1)='-',
#errStatusOK bit OUTPUT
My VBA to call the SP is below, but it won't work now, after adding the new parameter and I'm not sure where I'm going wrong, I keep getting 3708 - Parameter object is improperly defined. Inconsistent or incomplete information was provided.:
Set cnn = New adodb.Connection
cnn.ConnectionString =
"DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes"
cnn.Open cnn.ConnectionString
Set cmd = New adodb.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "stprMoveDataSet"
Set param = cmd.CreateParameter
("#DataSetID", adInteger, adParamInput, , stDataSet)
cmd.Parameters.Append param
Set param = cmd.CreateParameter
("#Destination", adChar, adParamInput, 1, stDestination)
cmd.Parameters.Append param
Set param = cmd.CreateParameter
("#errStatusOK", adBit, adParamReturnValue)
cmd.Parameters.Append param
rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.LockType = adLockOptimistic
rs.Open cmd
How can I get the vba to work with the OUTPUT parameter and make the return value 'readable' by the vba.
EDIT - I've changed the question to be more specifically about returning values and not just about using OUTPUT Parameters.
Several ways are possible to get values back using VBA.
Recordset
Count of records affected (only for Insert/Update/Delete otherwise -1)
Output parameter
Return value
My code demonstrates all four. Here is a stored procedure that returns a value:
Create PROCEDURE CheckExpedite
#InputX varchar(10),
#InputY int,
#HasExpedite int out
AS
BEGIN
Select #HasExpedite = 9 from <Table>
where Column2 = #InputX and Column3 = #InputY
If #HasExpedite = 9
Return 2
Else
Return 3
End
Here is the sub I use in Excel VBA. You'll need reference to Microsoft ActiveX Data Objects 2.8 Library.
Sub CheckValue()
Dim InputX As String: InputX = "6000"
Dim InputY As Integer: InputY = 2014
'open connnection
Dim ACon As New Connection
'ACon.Open ("Provider=SQLOLEDB;Data Source=<SqlServer>;" & _
' "Initial Catalog=<Table>;Integrated Security=SSPI")
'set command
Dim ACmd As New Command
Set ACmd.ActiveConnection = ACon
ACmd.CommandText = "CheckExpedite"
ACmd.CommandType = adCmdStoredProc
'Return value must be first parameter else you'll get error from too many parameters
'Procedure or function "Name" has too many arguments specified.
ACmd.Parameters.Append ACmd.CreateParameter("ReturnValue", adInteger, adParamReturnValue)
ACmd.Parameters.Append ACmd.CreateParameter("InputX", adVarChar, adParamInput, 10, InputX)
ACmd.Parameters.Append ACmd.CreateParameter("InputY", adInteger, adParamInput, 6, InputY)
ACmd.Parameters.Append ACmd.CreateParameter("HasExpedite", adInteger, adParamOutput)
Dim RS As Recordset
Dim RecordsAffected As Long
'execute query that returns value
Call ACmd.Execute(RecordsAffected:=RecordsAffected, Options:=adExecuteNoRecords)
'execute query that returns recordset
'Set RS = ACmd.Execute(RecordsAffected:=RecordsAffected)
'get records affected, return value and output parameter
Debug.Print "Records affected: " & RecordsAffected
Debug.Print "Return value: " & ACmd.Parameters("ReturnValue")
Debug.Print "Output param: " & ACmd.Parameters("HasExpedite")
'use record set here
'...
'close
If Not RS Is Nothing Then RS.Close
ACon.Close
End Sub
Set cnn = New adodb.Connection
cnn.ConnectionString =
"DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes"
cnn.Open cnn.ConnectionString
Set cmd = New adodb.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "stprMoveDataSet"
Set param1 = cmd.CreateParameter
("#DataSetID", adInteger, adParamInput, , stDataSet)
cmd.Parameters.Append param
Set param2 = cmd.CreateParameter
("#Destination", adChar, adParamInput, 1, stDestination)
cmd.Parameters.Append param
Set param3 = cmd.CreateParameter
("#errStatusOK", adBit, adParamOutput, , adParamReturnValue)
cmd.Parameters.Append param
rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.LockType = adLockOptimistic
rs.Open cmd
I'd initially looked at OUTPUT Parameters, but could not find out how to get them back to Access (in VBA) to then provide feedback to the user. A colleague suggested using a SELECT in the Stored procedure and to use this.
STORED PROCEDURE:
Added the following at the end:
SELECT #errStatusOK as errStatusOK, #countCurrent as countCurrent, #countHistorical as countHistorical
VBA:
Dim cnn As ADODB.Connection
Dim cmd As New ADODB.Command, rs As New ADODB.Recordset, param As New ADODB.Parameter
Dim fld As ADODB.Field
Dim stMessage As String
Set cnn = New ADODB.Connection
cnn.ConnectionString = "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes"
cnn.Open cnn.ConnectionString
Set cmd = New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "stprMoveDataSet"
Set param = cmd.CreateParameter("#DataSetID", adInteger, adParamInput, , stDataSet)
cmd.Parameters.Append param
Set param = cmd.CreateParameter("#Destination", adChar, adParamInput, 1, stDestination)
cmd.Parameters.Append param
rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.LockType = adLockOptimistic
'rs.Open cmd
Set rs = cmd.Execute
If rs!errstatusok = True Then
stMessage = "Operation appears to have been successful, check the DataSets Listing..." & Chr(13) & "Also, the Server returned the following information: ["
Else
stMessage = "Operation appears to have failed, check the DataSets Listing..." & Chr(13) & "Also, the Server returned the following information: ["
End If
For Each fld In rs.Fields
stMessage = stMessage & "| " & fld.Name & " / " & fld.Value & " |"
Next fld
stMessage = stMessage & "]"
MsgBox stMessage
This returns the folliwing:
Operation appears to have failed, check the DataSets Listing...
Also, the Server returned the following information: [| errStatusOK / False || countCurrent / 0 || countHistorical / 10 |]
Among the other parameter enumerations from which "adParamInput" is taken, another is "adParamOutput", which is to indicate an out parameter from a stored procedure, and "adParamInputOutput" for a parameter which goes "both directions," as it were. In your case, I believe "adParamOutput" would be appropriate. I hope this is what you're looking for.
This works:
Dim rst As New ADODB.Recordset
rst.Open "SELECT * FROM dbo.ftblTest(1,2,3)", CP.Connection, adOpenKeyset, adLockReadOnly
But it would be nicer to do this:
rst.Open "SELECT * FROM dbo.ftblTest(#Param1=1,#Param2=2,#Param3=3)", CP.Connection, adOpenKeyset, adLockReadOnly
If I try the second method I get the error: "parameters were not supplied for the function ftblTest"
Is it possible to use named parameters with multi-statement table-valued functions?
Edit 1: Examples Added Using Command Object
First the SQL
create function ftblTest (#Input int)
RETURNS #Results TABLE (
OutputField int
)
AS
BEGIN
INSERT INTO #Results SELECT #Input
Return
End
Some Code (run from inside an Access 2003 ADP, with a connection to the correct SQL DB)
Public Sub test()
Dim rst As New ADODB.Recordset
Dim cmd As New ADODB.Command
'method 1 works
rst.Open "SELECT * FROM dbo.ftblTest(2)", CurrentProject.Connection, adOpenKeyset, adLockReadOnly
Debug.Print rst.Fields(0)
rst.Close
With cmd
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdTable
'method 2 works
.CommandText = "dbo.ftblTest(3)"
Set rst = cmd.Execute
Debug.Print rst.Fields(0)
'method 3 fails
.CreateParameter "#Input", adInteger, adParamInput, , 4
.CommandText = "dbo.ftblTest(#Input)"
Set rst = cmd.Execute 'error here:-2147217900 Must declare the scalar variable "#Input".
Debug.Print rst.Fields(0)
End With
End Sub
How can I get the named parameters to work in method 3?
Edit 2: test code modified to use Parameters.Append
Public Sub test()
Dim rst As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim p As New ADODB.Parameter
With cmd
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdTable
'Parameter Append method fails
p = .CreateParameter("#Input", adInteger, adParamInput, , 4)
Debug.Print p.Name, p.Type = adInteger, p.Direction = adParamInput, p.SIZE, p.Value 'note that name not set!
With p
.Name = "#Input"
.Type = adInteger
.Direction = adParamInput
.SIZE = 4 'this shouldn't be needed
.Value = 4
End With
Debug.Print p.Name, p.Type = adInteger, p.Direction = adParamInput, p.SIZE, p.Value 'properties now set
.Parameters.Append p
.CommandText = "dbo.ftblTest(#Input)"
Set rst = cmd.Execute 'error here:-2147217900 Must declare the scalar variable "#Input".
Debug.Print rst.Fields(0)
End With
End Sub
this still doesn't work.
Edit 3: I removed the # from create parameter
as suggested and tried the CommandText 3 ways and got 3 different errors:
.CommandText = "dbo.ftblTest"
error: Parameters were not supplied for the function 'dbo.ftblTest'.
.CommandText = "dbo.ftblTest()"
error: An insufficient number of arguments were supplied for the procedure or function dbo.ftblTest.
.CommandText = "dbo.ftblTest(Input)"
error: "Input" is not a recognized table hints option. If it is intended as a parameter to a table-valued function or to the CHANGETABLE function, ensure that your database compatibility mode is set to 90.
This should work:
Dim cmd As New ADODB.Command
With cmd
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdTable
'you need to add question a mark for each parameter
.CommandText = "dbo.ftblTest(?)"
'you can even add a order by expression like:
.CommandText = "dbo.ftblTest(?) ORDER BY ..."
.Parameters.Append .CreateParameter("#Input", adInteger, adParamInput, , 4)
Set rst = cmd.Execute
Debug.Print rst.Fields(0)
End With
Yes, you can use parameters with a table function.
rst.Open "SELECT * FROM dbo.ftblTest(#Param1,#Param2,#Param3)", CP.Connection, adOpenKeyset, adLockReadOnly
Before you open the database connection add parameters and set their values.
Don't use the # in the name of your parameter and don't list the parameter by name in the command text. I've always done this with a stored procedure, so I'm not sure exactly how the paranethesis are handle for the command text.
try:
.CreateParameter "Input", adInteger, adParamInput, , 4
And:
.CommandText = "dbo.ftblTest()"
Or:
.CommandText = "dbo.ftblTest"