I've searched for answers to this, but none I've found have really helped. I have a stored procedure that writes data to a table. The insert includes a DateTime field, but this field can be empty depending on what data is entered. The code in my Classic ASP page is similar to the following:
If Request.Form("Status") = "Closed" Then
Status = "Closed"
DateClosed = Now()
Else
Status = "OPEN"
DateClosed = NULL
End If
SP_AddToTable = "MyTable '" & Status & "', '" & DateClosed & "'"
Set SQLQuery = objConn.Execute(SP_AddToTable)
The stored procedure looks like this:
USE [MyDatabase]
GO
/****** Object: StoredProcedure [dbo].[SP_AddToTable] Script Date: 04/30/2013 10:00:10 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_AddToTable]
#Status varchar(20),
#DateClosed datetime
AS
INSERT INTO MyTable (
[Status],
DateClosed,
)
VALUES (
#Status,
#DateClosed)
If I pass an actual date value, it works fine, but if the NULL value is passed, or if I don't pass any data to the DateClosed field then the field defaults to 1 Jan 1900. What do I need to do (either in my ASP code, or in the stored procedure) to leave the DateClosed field empty in the table?
I'm quite new to stored procedures, so please excuse any beginners errors. :)
Thanks.
First, you need to change your ASP code to call the sp using parameterized queries -- your query above is highly vulnerable to SQL Injection:
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = objConn
cmd.CommandText = "SP_AddToTable"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh
cmd.Parameters(1) = Status
cmd.Parameters(2) = DateClosed
cmd.Execute
This should also fix your null issue as before you were inserting the value 'NULL' (with single quotes).
Related
I have a form. Its data must be inserted into database (sql server 2008). I have written procedure to insert. How can i insert form data using stored procedure in classic ASP? Need some help as am new to asp and ado.
ALTER PROCEDURE INSERTVALUE
#COMPANY_ID INT ,
#COMPANY_NAME VARCHAR(20),
#SALES_REP VARCHAR (20),
#CONTRACT_ADMIN VARCHAR (20)
AS
BEGIN
INSERT INTO [form].[dbo].[COMPANY]
([COMPANY_ID]
,[COMPANY_NAME]
,[SALES_REP]
,[CONTRACT_ADMIN])
VALUES (#COMPANY_ID,#COMPANY_NAME,#SALES_REP,#CONTRACT_ADMIN);
END
GO
Edit (originally and wrongly posted as answer)
I tried to execute the following code but error occurs. ADODB.Command error '800a0bb9' Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another. /AddForm.asp, line 15 –
set rs=Server.CreateObject("ADODB.recordset")
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cnn
sql = " SELECT * FROM COMPANY"
rs.Open sql, cnn
If Request("submit") <> "" Then
cmd.CommandText = "INSERTVALUE"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("#COMPANY_ID",adint,adParamInput,10,Request.form("CompanyId"))
cmd.Parameters.Append cmd.CreateParameter("#COMPANY_NAME",advarchar,adParamInput,10, Request.form("company_name"))
cmd.Parameters.Append cmd.CreateParameter("#SALES_REP",advarchar,adParamInput,10,Request.form("sales_rep"))
cmd.Parameters.Append cmd.CreateParameter("#CONTRACT_ADMIN",advarchar,adParamInput,10, Request.form("contract_admin"))
cmd.Execute
End If
One possible cause of your problems and the tutorial don't tell you (or at least the ones I found didn't): if the adovbs.inc files is not found, it will give you:
ADODB.Comman error '800a0bb9'
Arguments are of the wrong type, are out of acceptable range, or are in conflict
with one another.
I had to explicitly include a copy of it.
I'm trying to execute the following SQL statement in an Excel Macro, but it fails to return a valid recordset. I suspect that having both an INSERT and a SELECT in the same statement is the culprit.
strSQL :
DECLARE #PurchOrdersTmpXl_A147 Table( SrNo INT, PONum VARCHAR(255));
INSERT INTO #PurchOrdersTmpXl_A147 (SrNo, PONum)
VALUES (1, 'PO0001968'),
(2, 'PO0000260');
SELECT
XLPO.SrNo [PO Order],
POOrigLine.PURCHID [Orig PO],
POOrigLine.ITEMID [Orig Item],
POOrigLine.Name [Orig Txt]
FROM
dbo.PURCHLINE POOrigLine
INNER JOIN #PurchOrdersTmpXl_A147 [XLPO]
ON POOrigLine.PurchID = XLPO.PONum
WHERE
POOrigLine.PurchStatus != 4
VBA Code
Set ADOConn = New ADODB.Connection
ADOConn.connectionString = strConnect
ADOConn.Open
Set ADOcmd = New ADODB.Command
ADOcmd.ActiveConnection = ADOConn
ADOcmd.CommandText = strSQL
Set ADOrs = ADOcmd.Execute
Debug.Print ADOrs.RecordCount // Gives error "Operation Not Allowed when object is closed"
Any help?
Thanks in advance.
Note 1:
I can confirm that this error is because I'm trying to execute an Insert query and a SELECT query in the same command string.
There are no errors if I use a temp table instead of the above table variable and split the command execution (execute the CREATE and INSERT first and then execute the SELECT).
However, as my temp table will never hold more than 20 records, I figure table variables would be more performance effective.
Try this:
Set ADOrs = New ADODB.Recordset
With ADOrs
.CursorLocation = adUseClient
Call .Open(strSQL, ADOConn, , , adCmdText)
If Not (.BOF And .EOF) Then Debug.Print .RecordCount
End With
In this case, the Command object is not needed; you only need the Recordset object.
Is it an option to turn this SQL into a stored procedure? You might have more luck that way as you can hide the other recordsets (which might be why it's closed)
Also is this the whole piece of SQL Code? Why not just select directly from the table? If you want to run this for a set of SrNo/PONum, then there is even more reason to run as a stored proc as you can pass table valued parameters.
http://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx
Here is an example stored proc that works for one set. See the link above for using many sets.
CREATE PROC p_Stuff
#SrNo INt, #PONum VARCHAR(255)
AS
SET NOCOUNT ON
DECLARE #PurchOrdersTmpXl_A147 Table( SrNo INT, PONum VARCHAR(255));
INSERT INTO #PurchOrdersTmpXl_A147 (SrNo, PONum)
VALUES (#SrNo, #PONum);
SELECT
XLPO.SrNo [PO Order],
POOrigLine.PURCHID [Orig PO],
POOrigLine.ITEMID [Orig Item],
POOrigLine.Name [Orig Txt]
FROM
dbo.PURCHLINE POOrigLine
INNER JOIN #PurchOrdersTmpXl_A147 [XLPO]
ON POOrigLine.PurchID = XLPO.PONum
WHERE
POOrigLine.PurchStatus != 4
and then execute as a stored procedure
EXEC p_Stuff 1, 'PO0001968'
System background: Coding in VBA using MS-Access 2010. Currently working on code behind module and calling stored procedure. The stored procedure is written in SQL and run on the Ms-SQL server 2008 application where the database is stored.
Stored Procedure: The stored procedure's purpose is to:
Retrieve three input parameters: WOID, SampleID and Analyte
Join two tables: tblWoSampleTest , tblTest
Select testID WHERE the three values match
note: WOID and SampleID column are in tblWoSampleTest and Analyte is in tbltest
Once the stored procedure is called, the testId is saved to a local variable ThisTestID
CREATE PROCEDURE upGetTestIDForAnalyte #WOID nvarchar(60), #SampleID nvarchar(60),#Analyte nvarchar(60), #TestId int OUT
AS
SELECT #TestID = (Select TestID = t1.TestID
FROM tblWOSampleTest t1
JOIN tblTest t2
ON t1.TestID=t2.TestID
WHERE #WOID = t1.WOID AND #SampleID = t1.SampleID AND #Analyte = t2.Analyte)
GO
My issue is every time I call the stored procedure, The value ThistestId was previously initialized to is returned even though I know the test Id exists and the stored procedure seemed to run correctly. To verify it exists I took my stored procedure and simply ran:
Select TestID = t1.TestID
FROM tblWOSampleTest t1
JOIN tblTest t2
ON t1.TestID=t2.TestID
WHERE #WOID = t1.WOID AND #SampleID = t1.SampleID AND #Analyte = t2.Analyte
and had the correct testId returned (there will only ever be one value). I don't think there is an issue with the data type because the testid is a number not a string. Also here is the way I call it, although I am pretty sure this method is correct.
ThisTestId = 5
Set Conn = New ADODB.connection
Conn.ConnectionString = "connection string"
Conn.Open
Set cmd = New ADODB.Command
cmd.ActiveConnection = Conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "upGetTestIDForAnalyte"
cmd.Parameters.Append cmd.CreateParameter("#Analyte", adVarChar, adParamInput, 60, Analyte)
cmd.Parameters.Append cmd.CreateParameter("#WOID", adVarChar, adParamInput, 60, ThisWOID)
cmd.Parameters.Append cmd.CreateParameter("#SampleID", adVarChar, adParamInput, 60, 1)
cmd.Parameters.Append cmd.CreateParameter("#testid", adDouble, adParamOutput, , ThisTestID)
cmd.Execute
Conn.Close
msgbox ThisTestId
In this case a 5 will be printed
Check that your your parameter is marked with OUTPUT keyword in your stored procedure
Try to specify adParamReturnValue for your output parameter
cmd.CreateParameter("#testid", adDouble, adParamOutput, , adParamReturnValue)
Then once you called the store procedure with cmd.Execute you have to read the value
ThisTestId = cmd.Parameters("#testid").Value
I'm pretty new to SQL, but where's your return?
http://msdn.microsoft.com/en-us/library/ms188655.aspx
You need to get the output parameter after command execution.
ThisTestId = Convert.ToInt32(cmd.Parameters("#testid").Value);
I am facing an issue where I need to calculate some data based on existing data, then insert that data and finally, return it to an Excel file using VBA.
I have successfully been able to create a stored procedure that returns a table of values after inserting:
[...]
INSERT INTO [ExcelRGA] (RM_prefix, RM_suffix, editing, createdBy, editedBy) values (#RM_prefix, #RM_suffix, 1, #user, #user);
DECLARE #tab table (RM varchar(20))
INSERT #tab SELECT (#RM_prefix +'-' + right('00' + #RM_suffix, 3)) as 'RM';
SELECT * FROM #tab
END
and this works! However, I am unable to get the values it is returning using VBA
Set oRS = New ADODB.Recordset
Set cmd = New ADODB.Command
Dim objRec As Object
cmd.ActiveConnection = oCon
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "dbo.newRM"
cmd.Parameters.Refresh
cmd.Parameters("#user").Value = "john"
Set oRS = cmd.Execute()
but I try to do something like
while not oRS.eof
....
wend
get an error message stating that the recordset is closed and I cannot do my thing.
All I am trying to do is secure the information that I have computed (RM_prefix and RM_suffix), insert them into my table and return them to my Excel file.
If there is a way to do this without using a store procedure (such as a function) that would also be great!
Please keep in mind that this is a multi-user environment, so generating the values in Excel, sending them to the SQL server for an insert doesn't give a 100% guarantee regarding the uniqueness of said data.
Thank you all for your precious help and inputs!
Peter
You need something like this -
Private Function GetIDENTITY() As Long
oRS.Open "SELECT ##identity AS NewID", oCon
If Not IsNull(oRS.Fields("NewID")) Then
GetIDENTITY = oRS.Fields("NewID"): oRS.Close
Else
MsgBox "Error: Identity value not returned.", vbCritical
End
End If
End Function
Actually, the issue was coming from the SQL Stored Procedure. I've added
SET NOCOUNT ON;
right before the
INSERT INTO [ExcelRGA] (RM_prefix, RM_suffix, editing, createdBy, editedBy) values (#RM_prefix, #RM_suffix, 1, #user, #user);
And it has solved my problem! I can now browse the recordset in VBA.
Thank you all for your help and inputs!
I have a stored procedure which selects a single field from a single row (based on a conditional statement) and stores it in a local variable. Based on the value of this field I update the same field in the same row of the table (using the same conditional statement). So the procedure first does a select into a local variable and then later updates the same field of the same row. The procedure then returns a result set via a select on a table variable (I have also attempted using a temporary table). The result set does not contain the variable or field I have updated. It doesn't even include any fields from this table.
The procedure works correctly when called from either Management Studio or from a test C# application. However, when called from my VB6 app the result set is not returned. All database updates are still performed however.
I have tried writing the stored procedure with a transaction and without, with TRY...CATCH and without, and both at the same time. I've tried various combinations of transaction isolation. No exceptions are thrown and the transaction will always commit. I've also used the WITH (NOLOCK) hint on the select statement. If I leave out the table update it will work. If I leave out the assignment to a local variable and instead hard code a value it works. If I simply use the select where I would put the variable it will NOT work.
Interestingly, if I add some random select statement to the procedure it will return that result set. I can even select that same field from the same record I assign to my variable with no issue. But it still will not return my desired result set.
My result set is a select from a table variable which is populated via insert statements using variables set throughout the procedure. There are no table joins at all. I do pass 2 parameters to the procedure - one of which is used in my conditional statement in the original select. But I still get the same behavior when I omit both parameters and hard code values.
I have tried restarting my SQL Server (2005 version 9.0.4053), restarting my machine, i have tried with NOCOUNT ON and OFF, I'm basically out of ideas.
Edit - Details of VB call and stored procedure signature:
I'll try to give as good as a description as I can without publishing actual code. I'm actually posting this for another developer who works with me, so please bear with me.
VB6 Call:
With cmdCommand
.ActiveConnection = cnnConn
.CommandType = adCmdStoredProc
.CommandText = "uspMyStoredProcedure"
.Parameters("#strParam1") = strFunctionParameter1
.Parameters("#bolParam2") = bolFunctionParameter2
.Execute
End With
MyResultSet.CursorLocation = adUseClient
MyResultSet.Open cmdCommand, , adOpenStatic, adLockReadOnly
Stored Procedure signature:
CREATE PROCEDURE uspMyStoredProcedure
#strParam1 NVARCHAR(XX),
#bolParam2 BIT
AS
BEGIN
SET NO COUNT ON
DECLARE #var1 NVARCHAR(XX),
#var2 NVARCHAR(XX),
#var3 NVARCHAR(XX),
#var4 INT,
#var5 BIT
--DECLARATION OF OTHER VARIABLES
DECLARE #varTableVariable TABLE
(
strTblVar1 NVARCHAR(XX) ,
intTblVar2 INT ,
strTblVar3 NVARCHAR(XX) ,
bolTblVar4 BIT ,
datTblVar5 DATETIME
)
SELECT #var1 = t.Field1, #var2 = t.Field2
FROM Table1 t
WHERE t.ID = #strParam1
SELECT #var3 = t2.Field1
FROM Table2 t2
IF (Condition)
BEGIN
SET #var4 = 1
IF (Condition)
BEGIN
--SET SOME VARIABLES
END
ELSE
BEGIN
UPDATE TABLE1
SET Field3 = #var4
WHERE Field1 = #strParam1
END
END
ELSE
BEGIN
IF(Condition)
BEGIN
SELECT #var5 = ISNULL(Condition)
FROM Table3 t3
WHERE t3.Field = #strParam1
--SET SOME MORE VARIABLES
END
END
IF(Condition)
BEGIN
UPDATE Table1
SET Field5 = #SomeVariable
WHERE Field1 = #strParam1
END
INSERT INTO Table4 (Field1, Field2, Field3)
SELECT #SomeVar1, #someVar2, #SomeVar3
FROM SomeOtherTable
WHERE Field3 = #someVariable
IF(Condition)
BEGIN
INSERT INTO #varTableVariable (strTblVar1, intTblVar2,
strTblVar3, bolTblVar4, datTblVar5 )
VALUES (#SomeVar1, #SomeVar2, #SomeVar3, #SomeVar4, #SomeVar5)
END
SELECT *
FROM #varTableVariable
END
So, essentially, the procedure takes two parameters. It carries out a number of simple operations - inserting and selecting data from a couple of different tables, an update to a table and inserting a row into a table variable.
The procedure finishes with a select from the table variable. There's nothing fancy about the procedure, or the call from VB6. As previously stated, the behaviour observed is unusual in that by commenting out certain sections the call and return will work - data is returned. Calling the same procedure from a C#.NET test app works and successfully returns the desired result.
All we manage to get back in the VB6 app is an empty recordset.
Edit 2: We've just found out that if we create an arbitrary table to hold the data to be returned by the final select statement instead of using a table variable, the procedure works...
We discovered that the stored procedure was actually executing twice, due to the way it was being called from VB6:
With cmdCommand
.ActiveConnection = cnnConn
.CommandType = adCmdStoredProc
.CommandText = "uspMyStoredProcedure"
.Parameters("#strParam1") = strFunctionParameter1
.Parameters("#bolParam2") = bolFunctionParameter2
.Execute
End With
MyResultSet.CursorLocation = adUseClient
MyResultSet.Open cmdCommand, , adOpenStatic, adLockReadOnly
The command object 'cmdCommand' is executed the first time with the explicit call as the final line in the 'With' statement, '.Execute'.
What we found was that the last line: 'MyResultSet.Open cmdCommand...' is also implicitly executing the stored procedure a second time.
Since the stored procedure's function is essentially to activate and deactivate an alarm, by executing twice we were getting the activation and deactivation occurring at once and therefore no resultset returned.
Hopefully this might help avoid someone else getting stuck on something like this.