Writing a SQL statement while declaring variables [closed] - sql-server

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am trying to write a SQL statement in a VB application. In this case, I need to declare two variables to call other stored procedures. This code works when I run it in SSMS, but I am not sure how to do it in VB.
Statement:
DECLARE #NewIncidentNoteId NVARCHAR(15)
EXEC uspGetNextId #NewIncidentNoteId OUTPUT
INSERT INTO [dbo].[IncidentNotes]
([Id]
,[IncidentId]
,[TaskId]
,[VLevel]
,[NotesSourceType]
,[Notes]
,[LogDate]
,[LogTime]
,[LogTZ]
,[LogBy]
,[LogByName]
,[NotifyFlg]
,[ActivityDate]
,[ActivityTime]
,[ShowInReport])
VALUES()
(#NewIncidentNoteId
,'60Z3M'
,''
,'1'
,'EIRInvestigatorComment'
,'This is a TEST note.'
,'20150416'
,'10:10:10'
,'UTC'
,'12876'
,'USER, ADMIN'
,'False'
,'20150416'
,'12:13:13'
,'1'))

First of all, as others have said, the best option would be to actually add it to the database as a stored procedure. Then you could just execute the stored procedure via a simple ADO.NET command. However, if you insist on sending the entire SQL script as a command, there are several ways to get it as a string.
VB doesn't currently have great support for multi-line string literals (long-overdue support for that is being added in VB.NET 14 as part of Visual Studio 2015). There are several workarounds. See this other answer of mine for some good options. However, for something like this, you may want to look into reading the script from an embedded resource or an external script file.

Set cmd = New ADODB.Command
cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "empdetails"
cmd.Parameters.Append cmd.CreateParameter_
("empid", adVarChar, adParamInput, 6, str_empid)
Set rs = cmd.Execute
If Not rs.EOF Then
txt_firstname = rs.Fields(0)
txt_title = rs.Fields(1)
txt_address = rs.Fields(2)
End If
Set cmd.ActiveConnection = Nothing
this code show how to use SP in vb6 not sure which vb you use if it is VB.net then you can use ADO.net to do that
this link might be helpful too
http://www.codeproject.com/Articles/15222/How-to-Use-Stored-Procedures-in-VB

Related

Ms-Access - invoke stored procedure that returns recordsset

I'm struggling with an old and massive system developed on MS-Access 2007, which I'm in charge of its maintenance (including the implementation of changes).
The system interacts with a SQL-Server (2012).
Currently, I need to implement a change in which a new stored procedure needs to be invoked which returns a simple records set, each record being a string.
I tried to use for the invocation some code that already exists within the application (using ADO and copied into the form I'm working on) but nothing I tried works.
Here is the code I'm trying to use:
glblsqlstrToLabels = "EXEC p_Labels_Print 1 , 2878954 , 'OC9991' , '89029' , 4 , 1 , 'dummy'"
Though I'm using exactly the same connection string as it is being used all over the application, executing the above statement returns with an error message (something like ...not open...).
I'm starting to suspect that there is something wrong in the way I'm invoking the function (e.g. not defining any parameters for it and expecting a behavior similar to a select statement).
Any help will be highly appreciated.
EDIT:
Following are the pieces of code describing what I need to have working:
Dim RS As Recordset
' Connection string is: Provider=Microsoft.Access.OLEDB.10.0;Persist Security Info=True;Data Source=****;User ID=****;Password=****;Initial Catalog=***;Data Provider=SQLOLEDB.1
MyCommand = "EXEC p_Labels_Print 1 , 2878954 , 'OC9991' , '89029' , 4 , 1 , 'asdasd'"
RS.Open MyCommand, CurrentProject.Connection
Do Until RS.EOF
Print <record retrieved>
Loop
RS.Close
Set RS = Nothing
The error I get is: Error: Operation is not allowed when the object is closed.
You need to properly use ADO and commands, you can't just rs.Open a stored procedure.
Use the following Microsoft boilerplate code:
Set Cmd1 = New ADODB.Command
Cmd1.ActiveConnection = Conn1
Cmd1.CommandText = "sp_AdoTest"
Cmd1.CommandType = adCmdStoredProc
Cmd1.Parameters.Refresh
Cmd1.Parameters(1).Value = 10
Set Rs1 = Cmd1.Execute()
Where Conn1 is your ADODB connection, and fill in your parameters and stored procedure name.

Two ways to execute a Stored procedure in VBA, Which one is better?

Background: Work on frontend Ms-Access 2010 and backend SQL server 2008 Managment Studio
For executing stored procedures I have been using a pretty lengthy process as seen here: in VBA
Set Conn = New ADODB.connection
Conn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;....."
Conn.Open
Set cmd = New ADODB.Command
cmd.ActiveConnection = Conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "upGetTestIdForAnalyte"
cmd.Parameters.Append cmd.CreateParameter("#WOID", adVarChar, adParamInput, 60, MySampleName)
cmd.Parameters.Append cmd.CreateParameter("#Analyte", adVarChar, adParamInput, 60, MyAnalyte)
cmd.Parameters.Append cmd.CreateParameter("#SampleID", adVarChar, adParamInput, 60, MyConcentration
cmd.Execute
Conn.Close
Someone told me there was a better way to execute a stored procedure and the correct way would be something like this: in VBA
strsql = "Exec upGetTestIdForAnalyte(WOID, Analyte, SampleID)"
test = ExecuteNonQuery(strsql)
But I got a lot of errors for this process and I looked up ExecuteNonQuery and it said it was only for VB (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx). One of the advantages of this process would be its conciseness and the fact that it connects automatically to the current database. I would have to change the connection string in my current sp process because it is set to link to a test database not the actual one. Another advantage would be that it returns a value when executed. I would like my current process to do that because I want to somehow verify it ran and other stored procedures I need to make, need to return the number of records affected.
My questions are: Is the second method a legitimate process and is that the correct syntax? Also is there any difference in what each process accomplishes? Also is there a way for the first process to return a value when executed? Thank you for your time.
UPDATE: This is my stored procedure I'm currently working on. My sp sees if a testID exists or not, I will continue with the program after calling the sp if variable ThisTestId >0 else I will raise an error testid not found
CREATE PROCEDURE upGetTestIDForAnalyte #WOID nvarchar(60), #SampleID nvarchar(60),#Analyte nvarchar(60), #Test var(20) output
AS
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
The examples posted here have way too much code.
The original question is the poster has seen some examples where only one or two lines of code is required.
In fact this code works and passes a parameter to a store procedure.
With CurrentDb.QueryDefs("MyPass")
.SQL = "exec MySproc" & ProducutID
.Execute
End If
The above is only two lines of code.
The advantages of this approach?
Note how we did not have to mess (or pass) with a connection string.
Note how we did not have to declare any connection object in code.
Note how we did not have to store or have the user name or password anywhere in the code.
Note how we don’t have to create a query def object in code either.
In fact the whole thing works without declaring ANY variables.
And the above could have been written on two lines of code, but I decided to post a massive 4 lines of code for increased readability.
The advantages of this setup are many, but the main reason is such an approach is MOST simple and easy to maintain.
The other posted solutions here serve only to force one to write many lines of code – this simply increases development costs for their employers.
I'll stay with first process and add an output parameter like this:
ccmd.parameters.Append ccmd.CreateParameter("OutParam", adInteger, adParamOuput, , NULL) ' output parameter
You need to add this parameter in stored procedure as well like this:
#OutParam int OUTPUT
EDIT Added OUT parameter, changed to integer in VBA code. See how ##ROWCOUNT work
CREATE PROCEDURE upGetTestIDForAnalyte #WOID nvarchar(60), #SampleID nvarchar(60),#Analyte nvarchar(60), #RecordsAfected int OUT
AS
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
set #recordsAfected = ##ROWCOUNT
GO
From Microsoft help site:
Function ExecuteSPT (sqltext As String, connectstring As String)
' Purpose: Run a temporary pass-through query.
' Accepts: sqltext: SQL string to run.
' connectstring: Connection string, which must be at least
' "ODBC;".
' Returns: nothing.
Dim mydb As Database, myq As QueryDef
Set mydb = DBEngine.Workspaces(0).Databases(0)
' Create a temporary QueryDef object that is not saved.
Set myq = mydb.CreateQueryDef("")
' Set the ReturnsRecords property to False in order to use the
' Execute method.
myq.returnsrecords = False
myq.connect = connectstring
myq.sql = sqltext
myq.Execute
myq.Close
End Function
It can be easily altered to return as DAO.Recordset. DAO is still the "native" data access in MS Access.

ADODB open recordset fails / "Operation is not allowed when object is closed"

I have the following UDF in excel which uses ADO to connect to my MSSQL server. There it should execute the scalar udf "D100601RVDATABearingAllow".
For some reason the parameters that I try to append are not send to the sql server. At the server only:
SELECT dbo.D100601RVDATABearingAllow
arrives.
MY EXCEL UDF:
Function RVDATA(Fastener) As Long
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Dim Cmd1 As ADODB.Command
Dim stSQL As String
Const stADO As String = "Provider=SQLOLEDB.1;Data ................"
'----------------------------------------------------------
Set cnt = New ADODB.Connection
With cnt
.ConnectionTimeout = 3
.CursorLocation = adUseClient
.Open stADO
.CommandTimeout = 3
End With
'----------------------------------------------------------
Set Cmd1 = New ADODB.Command
Cmd1.ActiveConnection = cnt
Cmd1.CommandText = "dbo.D100601RVDATABearingAllow"
Cmd1.CommandType = adCmdStoredProc
'----------------------------------------------------------
Set Param1 = Cmd1.CreateParameter("Fastener", adInteger, adParamInput, 5)
Param1.Value = Fastener
Cmd1.Parameters.Append Param1
Set Param1 = Nothing
'----------------------------------------------------------
Set rst = Cmd1.Execute()
RVDATA = rst.Fields(0).Value
'----------------------------------------------------------
rst.Close
cnt.Close
Set rst = Nothing
Set cnt = Nothing
'----------------------------------------------------------
End Function
When I use adCmdStoredProc the whole thing fails and in the vba debugger the properties of the recordset has a lot of "Operation is not allowed when object is closed" (may sound a bit different, the message is translated)
When I don't use adCmdStoredProc I get the message that the variable Fastener was not provided.
I think that maybe something is wrong in the way I open the recordset.
In other treads I read about using the "SET NOCOUNT ON" option, but that did not work either.
Does anyone have a idea?
Regards Lumpi
Ran into this error as well (in my case I am using a Stored Procedure to retrieve some information). I had made some changes which caused the execution to malfunction.
The error disappeared when I put SET NOCOUNT ON as the first statement of the Stored Procedure.
You do not need to SELECT the server side function, just provide its name ("[tra-CAE400-1].dbo.D100601RVDATABearingAllow") in the .CommandText property.
Also you should set the .CommandType property to "stored-procedure" (property reference on w3schools.com).
Then adodb will know that you are talking about calling a function, and not trying to send a plain sql-command.
Chances are that it will then allow you to define the parameters on the command object.
But the parameters you define on the command object should correspond exactly (in name and type) to the ones that are defined as the arguments of the function in the sql server.
An example from microsoft.com on using the command-object with a stored procedure
ADO Reference on microsoft.com
Another possible cause of this is debug statements. I just spent far too long trying to work out why this wouldn't work for me, the Proc on the database worked fine, the data it was supposed to insert was inserted, the VBA code worked fine, but there was nothing in the recordset.
Final solution was to go through the procs that had been built and remove the PRINT statements.
To test if this is the problem, run your proc on SQL Server manually, then look at the messages tab of the results, if there's anything there other than "Command(s) completed successfully." you need to eliminate those messages. "SET NOCOUNT ON" will get rid of the row count messages, but there may be others.
I'm assuming that after 5 years the OP has solved this particular problem, so this is just for anyone like me that finds this while searching for the same problem.
I also ran into this with a stored procedure. Did you SET NOCOUNT = OFF; at the bottom of your code? That is what worked for me after lots of googling. Also, if you have any other code that runs, you have to wrap it in Nocount = on/off, INCLUDING insert and update statements. You would think that an insert statement wouldn't matter but wrapping the code that way is what kept me from committing suicide today.
In our shop we often use lines like this in our stored procedures to assist with debugging:
RAISERROR('Debug message here',0,1) WITH NOWAIT;
This also breaks opening a recordset in Excel vba. I believe the complete answer for this question is, in the stored procedure:
use SET ROWCOUNT OFF
remove all PRINT statements
remove all RAISEERROR statements used for debugging (ie severity of 0)

ASP SQL Server query question

I am new to ASP. I've been coding with PHP for about 10 years now but just started ASP.
Here is my code:
Set rs = CreateObject("ADODB.Recordset")
strStoredProcedure = "SP_AddHPOrderItem'" & empIdent & "'"
rs.Open strStoredProcedure,strConnect, adopenForwardOnly, adlockoptimistic, adcmdtext
I am assuming that the variable RS("styleDesc") is coming from this query as I have found no reference to an RS, only rs. Not sure if variables are case sensitive in ASP.
My question is, is strStoredProcedure a function? Because I don't understand how this query can be made with the variable assigned the way it is.
How does SP_AddHPOrderItem'" & empIdent & "' constitute a query? There are no selects, inserts, updates, or anything like that.
If an expert could point me in the right direction if would be much appreciated.
The first statement of a SQL batch can be a stored procedure name; if so, SQL Server will execute it even if it's not prefixed with exec. So the net effect is if you send this to SQL Server:
exec SP_AddHPOrderItem 'empIdent'

SQL Server 2005 stored procedure fast in SSMS slow from VBA

I have a stored procedure which when run from SQL Server Management Studio consistently takes 5 seconds to run when called like this.
exec dbo.MyStoredProc '2009-04-30 00:00:00', '2009-04-30 20:00:00'
When called from an excel spreadsheet via VBA it takes 6 minutes plus (not including the time taken to copy the recordset to a sheet. The VBA is nothing fancy simply using an ADO connection to return a recordset. Unfortunately the Excel approach is a client requirement that I can't get rid of yet.
Public Function GenerateSQL(strQueryName As String) As Recordset
Dim rs As Recordset, cm As Command, dbsConn As Connection
Set dbsConn = New ADODB.Connection
dbsConn.Open Configuration.Range("ConnectionString")
Set cm = New ADODB.Command
With cm
.CommandText = strQueryName
.CommandType = adCmdStoredProc
.CommandTimeout = 300
.ActiveConnection = dbsConn
Set rs = .Execute()
End With
Set GenerateSQL = rs
End Function
Does anyone have any idea why this would happen or how I could begin to trace what is happening?
Thanks,
Steve
Everything you need to know about this topic: Slow in the Application, Fast in SSMS? Understanding Performance Mysteries
I believe I have the same problem as Steve Homer.
In addition to this SO question I also found this thread on eggheadcafe.com Very slow SP execution when using .net - very fast in Management Studio - totico
The answers say it's about parameter sniffing and how that affects which execution plan is used. The answers there specifically mentions the arithabort set option and how that affects the selection of plan.
Now I just need to find out how to change the set options from VBA...
Finally thanks to this forum entry on social.msdn.com i managed to get it right. First, set multiple connections to false:
connectionObject.Properties("Multiple Connections") = False
and then use the following function on your connection to set arithabort on ...
Private Sub OptionSet(ByRef cnn As adodb.Connection)
Dim cmd As adodb.Command
Set cmd = New adodb.Command
With cmd
Set .ActiveConnection = cnn
.CommandType = adodb.CommandTypeEnum.adCmdText
.CommandText = "set arithabort on"
Call .Execute
End With
Set cmd = Nothing
End Sub
Use SQL Server Profiler
Set up a trace on your database.
Limit the trace only to the stored procedure object in question
Limit to the username used by the VBA code
An introduction to SQL Server Profiler
In particular, check the SET options used by the connection and compare these with the defaults used when running the stored procedure in SSMS.
I have come across scenarios before where the SET options were different between calling code and within SSMS and the difference in performance was HUGE.
Thanks I'll take a look at the trace tools.
In reply to the comments on the original question
Are you using the exact same parameter values?
Yes exactly the same.
How much data is being returned (roughly) - number of rows and columns (and are any of them particularly big)?
Under 200 rows, perhaps 15 fields mostly ints with a couple of 20 character varchars.
Can you run SQL profiler and confirm if the sql is the issue or the remains of the macro in excel ?
The SQL is pretty ugly, as is the underlying database schema, and unfortunately is under NDA so I can't post it. If the query were the issue then wouldn't it be slow in management studio too though?

Resources