Below is a function I have in VB that will run a stored proc. The stored proc has 2 out parameters. One called #Success and one called #Message.
I am trying to set the success and message parameters to the values of the corresponding output params from the stored proc. I don't know much about VB.NET. How can I achieve this based off of the function I have currently written?
Public Function InvalidateCertificate(ByVal context As DbContextBase,
ByVal certificateId As System.String,
ByRef success As System.Boolean,
ByRef message As System.String) As Int32
Dim successParameter As New SqlParameter("#Success", success) With {.Direction = ParameterDirection.InputOutput, .Value = success}
Dim messageParameter As New SqlParameter("#Message", message) With {.Direction = ParameterDirection.InputOutput, .Value = message}
Dim parameters() As SqlParameter = {New SqlParameter("#CertificationValue", certificateId), successParameter, messageParameter}
Dim results As Int32 = context.ExecuteProcedure("Orders.spInvalidateCertificate", parameters)
success = DirectCast(successParameter.Value, System.Boolean)
message = DirectCast(messageParameter.Value, System.String)
Return 0
End Function
Stored proc:
ALTER PROCEDURE [Orders].[spInvalidateCertificate]
-- Add the parameters for the stored procedure here
#CertificationValue VARCHAR(20),
#Success BIT OUTPUT,
#Message VARCHAR(50) OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Log the call to this procedure
EXEC [Logs].[spLogStoredProcedureCall] ##PROCID;
--Check to see if CertificationValue exists or is invalid
IF(select CertificationValue from
[Certificate].CertificateOrderDetailImageXref where CertificationValue =
#CertificationValue) is null
BEGIN
SET #Success = 0
SET #Message = 'Certification does not exist or is already
invalidated.'
END
ELSE
BEGIN
-- Insert statements for procedure here
UPDATE Certificate.CertificateOrderDetailImageXref
SET CertificationValue = CONCAT(#CertificationValue,'-VOID')
WHERE CertificationValue = #CertificationValue
SET #Success = 1
SET #Message = 'Success, certification has been invalidated.'
END;
END
GO
To note, what's actually happening is that only the first letter of the message is being returned. so if its a success, and the sql output should be "success!" I just get "S". If the certification does not exist I just get "C".
Related
I am just new in oracle and using procedure and still learning, but I have a problem how can I populate the combo box using store procedure? I already have a code but when I run it, it shows an error IndexOutOfRangedException was unhandled and Cannot find Column 1.
Here's my code
(Procedure/Oracle Sql:)
procedure cmbbox_location (o_output out o_refcur)
as
o_cur o_refcur;
begin
open o_cur for
select city_id, city_name from city;
o_output := o_cur;
end cmbbox_location;
(program/vb.net)
Private Sub Main_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
instantiate_dev()
ora_conn.Open()
populate_cmbbox_loc()
End Sub
Private Sub populate_cmbbox_loc()
instantiate_dev()
ora_conn.Open()
qr.populate_location()
cmblocation.DataSource = dt
cmblocation.ValueMember = dt.Columns(0).ColumnName
cmblocation.DisplayMember = dt.Columns(1).ColumnName
cmblocation.Text = ""
cmblocation.SelectedIndex = 0
End Sub
Public Function populate_location()
dt = New DataTable
bg.GetProcDataTable(connStr, "Location_Package.cmbbox_location")
cmd.Parameters.Add(New OracleParameter("O_OUTPUT", OracleDbType.RefCursor)).Direction = ParameterDirection.Output
adap_or.SelectCommand = cmd
adap_or.Fill(dt)
Return dt
ora_conn.Close()
End Function
The error you are getting indicates that you are indexing something that doesn't exist, it's possible/probable your stored procedure isn't returning anything. To address William Robertson's concern about the ref cursor:
There are any number of ways to output a ref cursor. The one I use the most is a ref cursor type defined in the package definition, for example:
CREATE OR REPLACE PACKAGE Location_Package IS
TYPE DataOutCursor IS REF CURSOR;
procedure cmbbox_location (o_output out DataOutCursor);
END Location_Package;
/
Then in the procedure in the package body:
CREATE OR REPLACE PACKAGE BODY Location_Package IS
procedure cmbbox_location (o_output out DataOutCursor) as
begin
open o_output for
select city_id, city_name from city;
end;
END;
/
I assume the error is occurring here:
cmblocation.ValueMember = dt.Columns(0).ColumnName
cmblocation.DisplayMember = dt.Columns(1).ColumnName
It is always best to make sure the data table has data first so wrap the combo box lines with:
IF dt.Rows.Count > 0 Then
' ..... assign the data table to the combo box
Else
' Some error message ...
End IF
This will get rid of the unhandled exception and help you to figure out the issue.
On last thing, your function needs to return a value (datatable):
Public Function populate_location() as Datatable
dt = New DataTable
bg.GetProcDataTable(connStr, "Location_Package.cmbbox_location")
cmd.Parameters.Add(New OracleParameter("O_OUTPUT", OracleDbType.RefCursor)).Direction = ParameterDirection.Output
adap_or.SelectCommand = cmd
adap_or.Fill(dt)
Return dt
ora_conn.Close()
End Function
I have the following stored procedure:
CREATE PROCEDURE MyProc
#posted_xml_body xml
AS
INSERT INTO MyTable
(post_datetime, post_body)
VALUES
(getdate(), #posted_xml_body)
And the following VB code:
Using aConnection As New Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings(connectionString).ConnectionString)
aConnection.Open()
Dim aCommand As New Data.SqlClient.SqlCommand("MyProc", aConnection)
aCommand.CommandType = Data.CommandType.StoredProcedure
aCommand.Parameters.AddWithValue("#posted_xml_body", aXMLString)
Dim rows_affected As Integer = aCommand.ExecuteNonQuery()
aCommand.Dispose()
aConnection.Close()
Return rows_affected
End Using
However, I keep receiving the following error
"Procedure or function has too many arguments specified."
Thanks for any suggestions.
You pasted wrong or is missing a ")" here
VALUES
(getdate(), #posted_xml_body)
There are couple things I would suggest.
chang the column type to nvarchar(max), select scope identity, just make sure your table as a primary key because you vb code will give you an exception trying to convert date to integer.
CREATE PROCEDURE MyProc
#posted_xml_body as nvarchar(max)
AS
Begin
INSERT INTO MyTable
(post_datetime, post_body)
VALUES
(getdate(), #posted_xml_body);SELECT SCOPE_IDENTITY()
END
Your Vb Code
Using aConnection As New Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings(connectionString).ConnectionString)
Dim rows_affected As Integer = 0
Try
aConnection.Open()
Dim aCommand As New Data.SqlClient.SqlCommand("MyProc", aConnection)
aCommand.CommandType = Data.CommandType.StoredProcedure
aCommand.Parameters.AddWithValue("#posted_xml_body", aXMLString)
rows_affected = aCommand.ExecuteScalar()
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
If aConnection.State = ConnectionState.Open Then
aConnection.Close()
End If
End Try
Return rows_affected
End Using
I've been trying to figure out this bug for a while now, some help would be appreciated. Thanks.
Here is my error message:
Procedure or function 'getAvailableSMSNumbers' expects parameter '#Election_ID', which was not supplied.
Here is my sql code:
CREATE PROCEDURE {databaseOwner}{objectQualifier}getAvailableSMSNumbers
#Election_ID nvarchar(20)
AS
SELECT *
FROM {databaseOwner}{objectQualifier}icc_sms_phones
LEFT JOIN {databaseOwner}{objectQualifier}icc_sms_elections ON sms_elections_sms_number = phones_number
WHERE sms_elections_sms_number IS NULL
OR sms_elections_id = #Election_ID
GO
Function:
Public Overrides Function getAvailableSMSNumbers(eventid As String) As IDataReader
Dim dtable As New DataTable
Using sqlconn As New SqlConnection(Me.ConnectionString)
Using sqlcomm As New SqlCommand
Using sqlda As New SqlDataAdapter
sqlcomm.Connection = sqlconn
sqlcomm.CommandType = CommandType.StoredProcedure sqlcomm.CommandText=GetFullyQualifiedName("getAvailableSMSNumbers")
sqlcomm.Parameters.AddWithValue("#Election_ID", eventid)
sqlda.SelectCommand = sqlcomm
sqlconn.Open()
sqlda.Fill(dtable)
sqlconn.Close()
Return dtable.CreateDataReader
End Using
End Using
End Using
End Function
Where the function is used:
Public Function getAvailableSMSNumbers(eventid As String) As List(Of phoneModel)
Dim numbers As New List(Of phoneModel)
Dim number As phoneModel
numbers = CBO.FillCollection(Of phoneModel)(dal.getAvailableSMSNumbers(eventid))
For Each number In numbers 'dal.getAvailableSMSNumbers(eventid).Rows
number = New phoneModel
With number
.val = ("PHONES_NUMBER").ToString
.text = String.Format("{0:# (###) ###-####}", Long.Parse(.val))
End With
numbers.Add(number)
Next
Return numbers
End Function
If you need anymore information, let me know, and I will add it.
This typically occurs if the object supplied as the value of your SQL parameter is NULL, but the stored procedure does not allow null values (which yours does not). You can set a conditional breakpoint on this line sqlcomm.Parameters.AddWithValue("#Election_ID", eventid) to make sure the eventid parameter is not null.
It might also be a good idea to use defensive coding, and in your getAvailableSMSNumbers function, check to make sure eventid is not null, and if it is, throw an exception or provide some type of feedback for the user.
As an option you can try to re-compile your stored procedure to allow NULL parameter :
CREATE PROCEDURE {databaseOwner}{objectQualifier}getAvailableSMSNumbers
#Election_ID nvarchar(20) = NULL
AS
That means that the default value of your Parameter will be null in case there is no value on input. This solution will be nice in case you want to return empty datatable without error. In any other case you have to debug your VB code and understand where the issue starts.
Think about how you are calling you procedure. When you call you need to supply the value of the procedure: For example,
Call get_particular_girl_from_girlsTable("Jane")
where get_particular_girl_from_girlsTable is the procedure and "Jane" is value for parameter GirlName.
Did you verify if
cmd.CommandType = CommandType.**StoredProcedure**
By default, the value is Text, expecting a SELECT, INSERT or other command text.
I deliberately trigger a SqlException in the following insert statement in the code below and replaced the correct column name ModifiedBy by ModifiedB
You need to wrap the entire SQL Code in a transaction. Take this example:
create table errTest
(
intVal int
)
insert into errTest select 1
insert into errTest select 1/0
select * from errTest --one record
The second insert fails, but since no transaction was explicitly started, each insert is inherently its own transaction. The first succeeds, the second fails, and the table ends up retaining the successful insert.
If all inserts are wrapped in a transaction, and if xact_abort is on, then any error thrown by any insert will cause the entire transaction to rollback:
create table errTest
(
intVal int
)
set xact_abort on
begin transaction
insert into errTest select 1
insert into errTest select 1/0
commit transaction
select * from errTest --zero records
You need to pass your transaction and connection to all your commands you wish to use inside a SQL transaction, this is my example (I cut some things out using notepad so it might give errors in studio)
Private Sub main()
Using sql_conn
sql_conn.Open()
Dim SQL_transaction_INPUT As SqlClient.SqlTransaction = sql_conn.BeginTransaction
Try
Dim isOK as Boolean = False
isOK = update_BSE(myID, sql_conn, SQL_transaction_INPUT)
If isOK Then
SQL_transaction_INPUT.Commit()
sql_conn.Close()
Else
SQL_transaction_INPUT.Rollback()
sql_conn.Close()
End If
Catch ex As Exception
SQL_transaction_INPUT.Rollback()
If sql_conn.State = ConnectionState.Open Then sql_conn.Close()
End Try
End Using
End Sub
Private Function update_BSE(ByVal _IDmod As Integer, _
ByVal conn_with_trans As SqlConnection, _
ByVal conn_transaction As SqlTransaction) As Boolean
Dim ins As String = "UPDATE something WHERE IDrec = #IDmod"
Dim cmdINS As New SqlCommand(ins, conn_with_trans, conn_transaction)
Try
With cmdINS.Parameters
.Add("IDmod", SqlDbType.Int).Value = _IDmod
End With
cmdINS.ExecuteNonQuery()
Return True
Catch ex As Exception
Return False
End Try
End Function
I found a way to extract the contents of a MS Sql table directly (faster) to excel. But I do not know how to do this with a stored procedure that requires parameters. Is it possible to extract, directly, to an Excel File the results of a stored procedure? I know how to do it indirectly (using a data table) but it is too slow. Thank you very much.
PS: This is the method I was using to do some tests. It works with a table, but what I need is to extract the result of a stored procedure:
Private Sub SqlToExcelTest2(ByVal excelFilePath As String, _
ByVal nonExistingSheetName As String, _
ByVal sqlServer As String, _
ByVal sqlDatabase As String, _
ByVal sqlUserName As String, _
ByVal sqlPassword As String, _
ByVal sqlTable As String)
Const excelConnStrTemplate As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=YES;IMEX=2"";"
Dim connStr As String = String.Format(excelConnStrTemplate, _
excelFilePath)
Const adoQueryTemplate As String = "SELECT * INTO {0} FROM [odbc;Driver={{SQL Server}};" & _
"Server={1};Database={2};UID={3};PWD={4}].[{5}] "
Dim query As String = String.Format(adoQueryTemplate, _
nonExistingSheetName, _
sqlServer, _
sqlDatabase, _
sqlUserName, _
sqlPassword, _
sqlTable)
Using oleConn As New OleDb.OleDbConnection(connStr), oleCmd As New OleDb.OleDbCommand(query, oleConn)
oleConn.Open()
oleCmd.ExecuteNonQuery()
oleConn.Close()
End Using
End Sub
I do not have Excel right now to check, but you might try:
Start recording a new macro
on a new worksheet select menu Data->Import, and something like "data source"
choose your table/view (I am not sure if stored procedure is also supported)
setup all the credentials etc.
follow the rest of the steps...
stop recording macro
and take a look at the generated VBA code.
If you always run the same query (or few different ones), then creating few of such data sources with the auto-refresh on startup could be all you need.
Is Python an option for you?
A contrived stored procedure that takes a parameter and returns a result set:
create procedure usp_Temp #howmany tinyint
as
set nocount on
create table #tmp (ID int identity, Letter char(1), String varchar(50))
declare #i tinyint
set #i = 0
while #i < #howmany
begin
insert into #tmp (Letter, String) values('X', 'The quick brown fox...')
set #i = #i + 1
end
select * from #tmp
set nocount off
In Python, you could do something like this:
import dbi
import odbc
import csv
conn_str = 'Driver={SQL Server};Server=MyServer;Database=MyDb;Uid=MyLogin;Pwd=MyPwd'
conn = odbc.odbc(conn_str)
curs = conn.cursor()
curs.execute('exec usp_temp #howmany = 15')
results = curs.fetchall()
curs.close()
conn.close()
writer = csv.writer(open('tmp.csv', 'wb'), delimiter = ',',
quoting = csv.QUOTE_MINIMAL)
for result in results: writer.writerow(result)
Excel should be able to open up that CSV file without a problem.