How to get Scalar-value-function result VB.net form through stored procedure - sql

VB.Net Code
' Getting Records Before Transfer to GL
Call OpenAccConnection(lblUserName.Text, lblPassword.Text)
Dim odcTotalsForTransferGL As OleDbCommand = New OleDbCommand("spPet_TotalsForTransferGL", conAccounts)
odcTotalsForTransferGL.CommandType = CommandType.StoredProcedure
' Parameter Assigning
Dim strCompanyCode As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#ComCod", OleDbType.VarChar, 2)
strCompanyCode.Direction = ParameterDirection.Input
Dim strLocationCode As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#LocCod", OleDbType.VarChar, 2)
strLocationCode.Direction = ParameterDirection.Input
Dim strPettyCashDate As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#PetDat", OleDbType.VarChar, 8)
strPettyCashDate.Direction = ParameterDirection.Input
Dim strBegVNo As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#BegVNo", OleDbType.Integer)
strBegVNo.Direction = ParameterDirection.Output
Dim strEndVNo As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#EndVNo", OleDbType.Integer)
strEndVNo.Direction = ParameterDirection.Output
Dim strVouTotal As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#VouTotal", OleDbType.Integer)
strVouTotal.Direction = ParameterDirection.Output
Dim decPetTotal As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#PetTotal", OleDbType.Decimal)
decPetTotal.Direction = ParameterDirection.Output
Dim intFinancialDates As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#FinancialDates", OleDbType.Integer)
intFinancialDates.Direction = ParameterDirection.Output
' Passing Parameters
' Company Code
strCompanyCode.Value = cboCompanyCode.SelectedItem.ToString.Substring(0, 2)
' Location Code
strLocationCode.Value = cboLocationCode.SelectedItem.ToString.Substring(0, 2)
' Petty Cash Date(Year & Month)
strPettyCashDate.Value = dtPettyCashDate.Value.Year.ToString + dtPettyCashDate.Value.Month.ToString("D2") + "01"
' Accounts Database Open
conAccounts.Open()
' Stored Procedure Process
Dim odrTotalsForTransferGL As OleDbDataReader = odcTotalsForTransferGL.ExecuteReader()
If odrTotalsForTransferGL.HasRows Then
Do While odrTotalsForTransferGL.Read
lblAccPeriod.Text = odrTotalsForTransferGL.GetValue(4).ToString.Substring(0, 4) + "/" + odrTotalsForTransferGL.GetValue(4).ToString.Substring(5, 4)
lblFiscalMonth.Text = odrTotalsForTransferGL.GetValue(4).ToString.Substring(9, 2)
lblBegVNo.Text = odrTotalsForTransferGL.GetValue(0).ToString
lblEndVNo.Text = odrTotalsForTransferGL.GetValue(1).ToString
lblPettyTotal.Text = odrTotalsForTransferGL.GetValue(3).ToString
Loop
End If
Stored Procedure
ALTER PROCEDURE [dbo].[spPet_TotalsForTransferGL]
-- Add the parameters for the stored procedure here
#ComCod as varchar(2),
#LocCod as varchar(2),
#PetDat as varchar(8),
#BegVNo as int OUT,
#EndVNo as int OUT,
#VouTotal as int OUT,
#PetTotal as decimal(12,2) OUT,
#FinancialDates as varchar(10) OUT
AS
BEGIN
SELECT MIN(PettyDetail.DPetVouNo),
MAX(PettyDetail.DPetVouNo),
MAX(PettyDetail.DPetVouNo) - MIN(PettyDetail.DPetVouNo),
ISNULL(SUM(PettyDetail.DPetAmount), 0)
FROM PettyDetail
WHERE (PettyDetail.DPetComCode = #ComCod) AND
(PettyDetail.DPetLocCode = #LocCod) AND
(YEAR(PettyDetail.DPetDate) = YEAR(CONVERT(Date,#PetDat,111))) AND
(MONTH(PettyDetail.DPetDate) = MONTH(CONVERT(Date,#PetDat,111)))
/* Getting Financial Dates */
EXECUTE #FinancialDates = dbo.fnApp_GetFinancialDates #PetDat
END
Scalar Function
ALTER FUNCTION [dbo].[fnApp_GetFinancialDates]
(
-- Add the parameters for the function here
#PetDat as varchar(8)
)
--RETURNS int(10)
RETURNS varchar(10)
AS
BEGIN
-- Declare the return variable here
--DECLARE #FinancialDates int(10)
DECLARE #FinancialDates varchar(10)
-- Add the T-SQL statements to compute the return value here
IF MONTH(CONVERT(date,#PetDat,111)) BETWEEN 4 AND 12
BEGIN
SELECT #FinancialDates = (SELECT
CAST((YEAR(CONVERT(date,#PetDat,111))) as varchar) +
CAST((YEAR(CONVERT(date,#PetDat,111)) + 1) as varchar) +
REPLICATE('0',(2-(LEN(CAST((MONTH(CONVERT(date,#PetDat,111)) - 3) as varchar))))) + (CAST((MONTH(CONVERT(date,#PetDat,111)) - 3) as varchar)))
END
ELSE
BEGIN
SELECT #FinancialDates = (SELECT
CAST((YEAR(CONVERT(date,#PetDat,111)) - 1)as varchar) +
CAST((YEAR(CONVERT(date,#PetDat,111))) as varchar) +
CAST((MONTH(CONVERT(date,#PetDat,111)) + 9) as varchar))
END
-- Return the result of the function
RETURN #FinancialDates
END
Above function #FinancialDates value didn't return to the .Net form. But other results are return to form.
Can any one please help me to solve this problem. Procedure & Function run correctly in Query Manager.

Two options :
Option 1 : change EXECUTE #FinancialDates = dbo.fnApp_GetFinancialDates #PetDat,
to :
SET #FinancialDates = dbo.fnApp_GetFinancialDates(#PetDat)
Option 2 : Include your fnApp_GetFinancialDates function in your SELECT statement (and you could just remove the #FinancialDates as varchar(10) OUT parameter statement.
ALTER PROCEDURE [dbo].[spPet_TotalsForTransferGL]
-- Add the parameters for the stored procedure here
#ComCod as varchar(2),
#LocCod as varchar(2),
#PetDat as varchar(8)
AS
BEGIN
SELECT MIN(PettyDetail.DPetVouNo) AS 'BegVNo',
MAX(PettyDetail.DPetVouNo) AS 'EndVNo',
MAX(PettyDetail.DPetVouNo) - MIN(PettyDetail.DPetVouNo) AS 'VouTotal',
ISNULL(SUM(PettyDetail.DPetAmount), 0) AS 'PetTotal'
dbo.fnApp_GetFinancialDates (#PetDat) AS 'FinancialDates'
FROM PettyDetail
WHERE (PettyDetail.DPetComCode = #ComCod) AND
(PettyDetail.DPetLocCode = #LocCod) AND
(YEAR(PettyDetail.DPetDate) = YEAR(CONVERT(Date,#PetDat,111))) AND
(MONTH(PettyDetail.DPetDate) = MONTH(CONVERT(Date,#PetDat,111)))
END
and for the option 2 VB code :
If odrTotalsForTransferGL.HasRows Then
Do While odrTotalsForTransferGL.Read
lblAccPeriod.Text = odrTotalsForTransferGL("FinancialDates").ToString.Substring(0, 4) + "/" + odrTotalsForTransferGL("FinancialDates").ToString.Substring(5, 4)
lblFiscalMonth.Text = odrTotalsForTransferGL("FinancialDates").ToString.Substring(9, 2)
lblBegVNo.Text = odrTotalsForTransferGL("BegVNo").ToString
lblEndVNo.Text = odrTotalsForTransferGL("EndVNo").ToString
lblPettyTotal.Text = odrTotalsForTransferGL("PetTotal").ToString
Loop
End If
edited : and don't forget to remove the following code because they are not necessary and will produce errors since the stored proc has no output parameters anymore:
Dim strBegVNo As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#BegVNo", OleDbType.Integer)
strBegVNo.Direction = ParameterDirection.Output
Dim strEndVNo As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#EndVNo", OleDbType.Integer)
strEndVNo.Direction = ParameterDirection.Output
Dim strVouTotal As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#VouTotal", OleDbType.Integer)
strVouTotal.Direction = ParameterDirection.Output
Dim decPetTotal As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#PetTotal", OleDbType.Decimal)
decPetTotal.Direction = ParameterDirection.Output
Dim intFinancialDates As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#FinancialDates", OleDbType.Integer)
intFinancialDates.Direction = ParameterDirection.Output

Related

How do I create a single query for multiple optional search parameters in a parameterized query?

I'm working on a Report form where a user inputs multiple values on textboxes and I take those values and I perform parameterized query search.
My current issue is a report form that has 8 total parameters but has a minimum requirement of three values being: Store_ID, From_date and To_Date. What I want to do is to have a single query that performs a search with the given values. So that I wont have to create cases or if else statement for each possible combination of those 8 parameters.
I would appreciate if someone can provide an example of on how to do that.
For additional context is for a report form Web application build using Visual Studio .NET with Visual basic.
EDIT: I made the modifications to the query as suggested in the comments.
My current query works but only if all the values are provided. But if I don't add one of the optional query parameters I get the following error:
System.FormatException: 'Input string was not in a correct format.'
I suspect this error is because I didn't assign a value to a parameter.
Or that perhaps the AND H.Rgst_ID IS NULL statement might be causing a SQL error and doesn't perform the search.
How can I fix this error so that my query accepts blank/null inputs?
This is my current code:
SQLControl
Imports System.Data.SqlClient
Public Class SQLControl
Private ReadOnly ConStr As String = "String"
Private DBCmd As SqlCommand
'Query Parameters
Public Params As New List(Of SqlParameter)
'This generates a blank sqlclient class with the deafult connection string
Public Sub New()
End Sub
'Allow connection string override
Public Sub New(connectionString As String)
ConStr = connectionString
End Sub
'Execute Query Sub
Public Function ExecQuery(query As String) As DataTable
Dim DBDT = New DataTable
Using DBCon As New SqlConnection(ConStr),
DBCmd As New SqlCommand(query, DBCon)
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
Params.Clear()
DBCon.Open()
DBDT.Load(DBCmd.ExecuteReader)
End Using
Return DBDT
End Function
'Add Params
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New SqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
Web Form code:
Protected Sub ExecuteButton_Click(sender As Object, e As EventArgs) Handles ExecuteButton.Click
Dim StoreID As Integer
Dim TransID As Integer
Dim RgstID As Integer
Dim FromDate As DateTime
Dim ToDate As DateTime
Dim DiscCD As Integer 'This is selected from the item list
Dim DiscPercent As Double
Dim DiscAmount As Double
'The minimum required search paraeters are Store_ID, From_Date and To_Date. The rest of the parameters are optional
'StoreID Validation
If Not Integer.TryParse(StoreIDTextbox.Text, StoreID) Then
MsgBox("Invalid input. Please enter Store ID.")
Exit Sub
End If
'FromDateValidation
If Not DateTime.TryParse(FromDateTextbox.Text, FromDate) Then
MsgBox("Invalid input. Please enter from date")
Exit Sub
End If
'ToDateValidation
If Not DateTime.TryParse(ToDateTextbox.Text, ToDate) Then
MsgBox("Invalid input. Please enter to date.")
Exit Sub
End If
Integer.Parse(RegisterIDTextbox.Text, RgstID)
Integer.Parse(TransactionIDTextbox.Text, TransID)
Integer.Parse(ListBox1.SelectedValue, DiscCD)
Double.Parse(DiscountPercentTextbox.Text, DiscPercent)
Double.Parse(DiscountAmtTextbox.Text, DiscAmount)
Dim pct As Double
pct = DiscPercent / 100
Dim amt As Double
amt = DiscAmount * -1
'Adds parameter to the query
SQL.AddParam("#Str_ID", StoreID)
SQL.AddParam("#FromDate", FromDate)
SQL.AddParam("#ToDate", ToDate)
SQL.AddParam("#Rgst_ID", RgstID)
SQL.AddParam("#Trans_ID", TransID)
SQL.AddParam("#DiscType", DiscCD)
SQL.AddParam("#DisPct", pct)
SQL.AddParam("#DisAmt", amt)
Dim dt As DataTable
Try
dt = SQL.ExecQuery("SELECT H.Str_ID, H.Rgst_ID, H.Tran_ID, L.Tran_LN_Num, H.Bus_DT, H.Emp_ID, H.Cust_ID, LD.Auth_Emp_ID, L.Ext_Prc, LD.Disc_Amt, D.Descr, LD.Disc_Pct, LD.DisC_CD
FROM twOLTP.dbo.Transaction_Header H
INNER JOIN twOLTP.dbo.LN_Detail L ON (H.Str_ID = L.Str_ID AND H.Rgst_ID = L.Rgst_ID AND H.Tran_ID = L.Tran_ID)
INNER JOIN twOLTP.dbo.LN_Discount LD ON (L.Str_ID = LD.Str_ID AND L.Rgst_ID = LD.Rgst_ID AND L.Tran_ID = LD.Tran_ID AND L.Tran_Ln_Num = LD.Tran_Ln_Num)
LEFT JOIN twOLTP.dbo.Discount D ON (LD.Disc_CD = D.Disc_CD)
WHERE (H.Str_ID = #Str_ID)
AND (H.Bus_DT >= #FromDate)
AND (H.Bus_DT <= #ToDate)
AND (H.Rgst_ID IS NULL OR H.Rgst_ID = #Rgst_ID)
AND (H.Tran_ID IS NULL OR H.Tran_ID = #Trans_ID)
AND (LD.DisC_CD IS NULL OR LD.DisC_CD = #DiscType)
AND (LD.Disc_Pct IS NULL OR LD.Disc_Pct = #DisPct)
AND (LD.Disc_Amt IS NULL OR LD.Disc_Amt = #DisAmt) ")
Catch ex As Exception
MsgBox(ex.Message)
Exit Sub
End Try
GridView1.DataSource = dt
GridView1.DataBind()
EDIT I was able to solve the problem
For my query to accept blank/null inputs i had t do the following.
WHERE ((H.Rgst_ID = #Rgst_ID) Or (#Rgst_ID Is NULL Or #Rgst_ID = ''))
Thanks for the help
Your where clause might look like this... the first three params are required, the others are optional
WHERE
Store_ID = #Store_ID
AND
From_date = #From_date
AND
To_Date = #To_Date
AND
ISNULL(#param4,param_name_4) = param_name_4
AND
ISNULL(#param5,param_name_5) = param_name_5
AND
ISNULL(#param6,param_name_6) = param_name_6
AND
ISNULL(#param7,param_name_7) = param_name_7
AND
ISNULL(#param8,param_name_8) = param_name_8
As Dan mentioned in the comments under the question, you want to be able to maintain SARGability here. For a simple query, this means you can use an OR with an IS NULL on the parameter like this below:
SELECT ...
FROM dbo.YourTable YT
WHERE StoreID = #StoreID
AND FromDate = #FromDate
AND ToDate = #ToDate
AND (OtherColumn = #OtherParameter OR #OtherParameter IS NULL)
AND (AnotherColumn = #AnotherParameter OR #AnotherParameter IS NULL)
AND (SomeColumn = #SomeParameter OR #SomeParameter IS NULL)
AND (YetAnotherColumn = #YetAnotherParameter OR #YetAnotherParameter IS NULL)
AND (FinalColumn = #FinalParameter OR #FinalParameter IS NULL)
OPTION (RECOMPILE);
You need to, however, ensure you have OPTION (RECOMPILE) as SQL Server would generate a single plan based on this query. This is bad as the query has many different ways of running, and so a plan where 1 parameter has a non-NULL value would be vastly different to where none of them do. OPTION (RECOMPILE) forces the data engine to regenerate the plan as a result.
This, however, can come at a cost, and sometimes it better to stick to the "older" method us using dynamic SQL to generate the statement. This means that different statements are run, depending on what parameters have non-NULL values.
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET #SQL = N'SELECT ...' + #CRLF +
N'FROM dbo.YourTable YT' + #CRLF +
N'WHERE YT.StoreID = #StoreID' + #CRLF +
N' AND YT.FromDate = #FromDate' + #CRLF +
N' AND YT.ToDate = #ToDate' + #CRLF +
CASE WHEN #OtherParameter IS NOT NULL THEN N' AND YT.OtherColumn = #OtherParameter' + #CRLF + END +
CASE WHEN #AnotherParameter IS NOT NULL THEN N' AND YT.AnotherColumn = #AnotherParameter' + #CRLF + END +
CASE WHEN #SomeParameter IS NOT NULL THEN N' AND YT.SomeColumn = #SomeParameter' + #CRLF + END +
CASE WHEN #YetAnotherParameter IS NOT NULL THEN N' AND YT.YetAnotherColumn = #YetAnotherParameter' + #CRLF + END +
CASE WHEN #FinalParameter IS NOT NULL THEN N' AND YT.FinalColumn = #FinalParameter' + #CRLF + END + N';';
EXEC sys.sp_executesql #SQL,
N'#OtherParameter int, #AnotherParameter varchar(30), #SomeParameter date, #YetAnotherParameter decimal(12,2), #FinalParameter tinyint',
#OtherParameter,
#AnotherParameter,
#SomeParameter,
#YetAnotherParameter,
#FinalParameter;
Notice you need to declare all the parameters in the 2nd parameter for sys.sp_executesql and still pass them all, but if they have the value NULL then the executed query won't use them in the WHERE.

Why is there a syntax error in my update statement in vb.net?

I have been working on my Update Sql statement, but cannot find the syntax error in my code. My insert statement is working, and I am selecting their login Id from another form to compare against.
conn.Open()
Dim SqlUpdate As String = "UPDATE tblLogin SET UserPassword =#UserPassword , FirstName =#FirstName , Surname =#Surname , DateofBirth =#DateofBirth , Phonenumber =#Phonenumber , Emailaddress = #Emailaddress , Administrator = #Administrator , Height = #Height , Weight = #Weight , WHERE UserID = #UserID "
Dim SqlCommand As New OleDbCommand
With SqlCommand
.CommandText = SqlUpdate
.Parameters.AddWithValue("#UserPassword", passwordsubmitbox.Text)
.Parameters.AddWithValue("#FirstName", forenamebox.Text)
.Parameters.AddWithValue("#Surname", surnamebox.Text)
.Parameters.AddWithValue("#DateofBirth", DOBselection.Value)
.Parameters.AddWithValue("#Phonenumber", phonenumberbox.Text)
.Parameters.AddWithValue("#Emailaddress", emailadressbox.Text)
.Parameters.AddWithValue("#Administrator", "N")
.Parameters.AddWithValue("#Height", CInt(heightbox.Text))
.Parameters.AddWithValue("#Weight", CInt(weightbox.Text))
.Parameters.AddWithValue("#UserID", Formlogin.UsernameBox1.Text)
.Connection = conn
.ExecuteNonQuery()
End With
conn.Close()
Your query has syntax error remove , after #Weight
Weight = #Weight WHERE UserI ...

SQL / VB.NET - Query doesn't return to application

I've got a MSSQL procedure running fine from the SQL Management console, but when I try to run it from my VB.NET it simply never returns. Someone have any idea?
I am testing with the same database.
SQL CODE (PROCEDURE)
ALTER PROCEDURE [dbo].[P_DEN_L_IMPRESSAO_ORCAMENTOS_APROVADO_NOVO]
(
#PAC_D_DATA_INICIAL DATETIME = NULL,
#PAC_D_DATA_FINAL DATETIME = NULL,
#PAC_DET_N_CODIGO DECIMAL = NULL,
#PAC_CLI_N_CODIGO DECIMAL = NULL,
#PAC_EMP_N_CODIGO DECIMAL = NULL
)
AS
SELECT
PAC_N_CODIGO,
PAC_C_CODIGO_INTERNO,
PAC_C_NOME,
PAC_C_EMAIL,
PAC_C_TELEFONE_RES,
PAC_CLI_N_CODIGO,
CLI_C_DESCRICAO,
ODO_D_DATA_INICIO,
ODO_D_DATA_FINAL,
ODO_PTR_N_CODIGO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN
PAC_C_ENDERECO_RES +
CASE
WHEN PAC_C_NUMERO_RES IS NULL OR PAC_C_NUMERO_RES = '' THEN ''
ELSE ', ' + PAC_C_NUMERO_RES
END +
CASE
WHEN PAC_C_COMPLEMENTO_RES IS NULL OR PAC_C_COMPLEMENTO_RES = '' THEN ''
ELSE ', ' + PAC_C_COMPLEMENTO_RES
END
WHEN 2 THEN
PAC_C_ENDERECO_COM +
CASE
WHEN PAC_C_NUMERO_COM IS NULL OR PAC_C_NUMERO_COM = '' THEN ''
ELSE ', ' + PAC_C_NUMERO_COM
END +
CASE
WHEN PAC_C_COMPLEMENTO_COM IS NULL OR PAC_C_COMPLEMENTO_COM = '' THEN ''
ELSE ', ' + PAC_C_COMPLEMENTO_COM
END
END AS PAC_C_ENDERECO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN PAC_C_BAIRRO_RES
WHEN 2 THEN PAC_C_BAIRRO_COM
END AS PAC_C_BAIRRO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN PAC_C_CIDADE_RES
WHEN 2 THEN PAC_C_CIDADE_COM
END AS PAC_C_CIDADE,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN
(SELECT EST_C_RESUMIDO
FROM DEN_EST_ESTADO
WHERE EST_N_CODIGO = PAC_EST_N_CODIGO_RES)
WHEN 2 THEN
(SELECT EST_C_RESUMIDO
FROM DEN_EST_ESTADO
WHERE EST_N_CODIGO = PAC_EST_N_CODIGO_COM)
END AS EST_C_RESUMIDO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN PAC_C_CEP_RES
WHEN 2 THEN PAC_C_CEP_COM
END AS PAC_C_CEP,
ODO_N_VERSAO,
PAC_C_CELULAR,
PAC_DET_N_CODIGO,
ODO_N_CODIGO,
SUM(VIN_N_VALOR) as 'T_PROC',
(SELECT SUM(VIN_N_VALOR) FROM DEN_VIN_VINCULO_TRATAMENTO
WHERE VIN_OXD_ODO_N_CODIGO = ODO_N_CODIGO) as 'VIN_N_VALOR',
convert(decimal(18,2),0) AS 'T_ENTRADA'
FROM
DEN_PAC_PACIENTE
INNER JOIN
DEN_DET_DENTISTA
ON
DET_N_CODIGO = PAC_DET_N_CODIGO
AND
DET_CLI_N_CODIGO = PAC_CLI_N_CODIGO
INNER JOIN
DEN_CLI_CLINICA
ON
CLI_N_CODIGO = PAC_CLI_N_CODIGO
INNER JOIN
DEN_EMP_EMPRESA
ON
EMP_N_CODIGO = CLI_EMP_N_CODIGO
INNER JOIN
DEN_ODO_ODONTOGRAMA
ON
ODO_PAC_N_CODIGO = PAC_N_CODIGO
INNER JOIN
DEN_VIN_VINCULO_TRATAMENTO
ON
VIN_OXD_ODO_N_CODIGO = ODO_N_CODIGO
WHERE
(ODO_D_DATA_FINAL BETWEEN #PAC_D_DATA_INICIAL AND #PAC_D_DATA_FINAL)
AND
(ODO_PTR_N_CODIGO = 2)
AND
(ODO_B_APROVADO = 1)
AND
(#PAC_CLI_N_CODIGO IS NULL OR PAC_CLI_N_CODIGO = #PAC_CLI_N_CODIGO)
AND
(#PAC_DET_N_CODIGO IS NULL OR VIN_DET_N_CODIGO = #PAC_DET_N_CODIGO)
AND
(CLI_EMP_N_CODIGO = #PAC_EMP_N_CODIGO)
AND
(PAC_B_ATIVO = 1)
AND
(PAC_B_POTENCIAL = 0)
GROUP BY
PAC_N_CODIGO,
PAC_C_CODIGO_INTERNO,
PAC_C_NOME,
PAC_C_EMAIL,
PAC_C_TELEFONE_RES,
PAC_CLI_N_CODIGO,
CLI_C_DESCRICAO,
ODO_D_DATA_INICIO,
ODO_D_DATA_FINAL,
ODO_PTR_N_CODIGO,
ODO_N_VERSAO,
PAC_C_CELULAR,
PAC_DET_N_CODIGO,
ODO_N_CODIGO,
PAC_N_CORRESPONDENCIA,
PAC_C_ENDERECO_RES,
PAC_C_NUMERO_RES,
PAC_C_NUMERO_RES,
PAC_C_COMPLEMENTO_RES,
PAC_C_ENDERECO_COM,
PAC_C_NUMERO_COM,
PAC_C_COMPLEMENTO_COM,
PAC_C_BAIRRO_RES,
PAC_C_BAIRRO_COM,
PAC_C_CIDADE_RES,
PAC_C_CIDADE_COM,
PAC_EST_N_CODIGO_RES,
PAC_EST_N_CODIGO_COM,
PAC_C_CEP_RES,
PAC_C_CEP_COM
ORDER BY
PAC_C_NOME, ODO_N_VERSAO
VB.NET CODE
Public Function ListarOrcamentosAprovadoNovo(ByVal mdlPaciente As Paciente, _
ByVal datDataInicial As Date, _
ByVal datDataFinal As Date, _
ByVal pblnEtiqueta As Boolean, Optional ByVal pstrCodigos As String = "") As DataTable
Try
cmdCommand = New FWCommand
With cmdCommand
.CommandText = "P_DEN_L_IMPRESSAO_ORCAMENTOS_APROVADO_NOVO"
.CommandTimeout = intCommandTimeOut
.CommandType = CommandType.StoredProcedure
.Parameters.Add(New FWParameter("#PAC_D_DATA_INICIAL", FWDbType.DateTime))
.Parameters("#PAC_D_DATA_INICIAL").Value = datDataInicial
.Parameters.Add(New FWParameter("#PAC_D_DATA_FINAL", FWDbType.DateTime))
.Parameters("#PAC_D_DATA_FINAL").Value = datDataFinal
If mdlPaciente.CodDentista > -1 Then
.Parameters.Add(New FWParameter("#PAC_DET_N_CODIGO", FWDbType.Decimal))
.Parameters("#PAC_DET_N_CODIGO").Value = mdlPaciente.CodDentista
End If
If mdlPaciente.CodClinica > 0 Then
.Parameters.Add(New FWParameter("#PAC_CLI_N_CODIGO", FWDbType.Decimal))
.Parameters("#PAC_CLI_N_CODIGO").Value = mdlPaciente.CodClinica
End If
If mdlPaciente.CodEmpresa > 0 Then
.Parameters.Add(New FWParameter("#PAC_EMP_N_CODIGO", FWDbType.Decimal))
.Parameters("#PAC_EMP_N_CODIGO").Value = mdlPaciente.CodEmpresa
End If
End With
Return conProvider.ExecuteDataTable(cmdCommand)
Catch ex As Exception
Throw
Finally
cmdCommand = Nothing
End Try
End Function
Things to check:
Check that your .NET connection string is pointing to the same database that
you are using in your SSMS query
You are using different parameter values in you .NET code then when running in SSMS
This could be related to "parameter sniffing". Possible workarounds are
a) adding with(recompile) to the proc,
b) add a set of local variables that you copy the parameter values into and use the local variables in the query,
c) use OPTION (OPTIMIZE FOR (#VARIABLE UNKNOWN)), or
d) trace flag 4136 that can be used to disable the "parameter sniffing" process (http://support.microsoft.com/kb/980653)
See these articles for more details on parameter sniffing:
http://blogs.msdn.com/b/turgays/archive/2013/09/10/parameter-sniffing-problem-and-workarounds.aspx
http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

Transactions in vb.net locks table and SELECT gets timeout

I have the following problem:
Inside one sqltransaction in vb.net I INSERT data into several tables.
it is something like this:
...
sqltransaction = connection.begintransaction
INSERT into table1
...
for i=1 to x
...
INSERT into table2
...
SELECT FROM table3
...
INSERT into table3
...
next i
sqltransaction.commit
...
Private Sub salveazaCerereaDeOferta()
If checkCompletion() = 1 Then
Dim conn As New SqlConnection(My.Settings.GestiuneService2012_beSQLConnectionString)
conn.Open()
Dim sqlTrans As SqlTransaction = conn.BeginTransaction()
Try
Dim cmdInsertCerereOferta As SqlCommand = conn.CreateCommand
cmdInsertCerereOferta.Transaction = sqlTrans
cmdInsertCerereOferta.CommandText = "INSERT INTO ListaCereriOferte (IDFurnizor,NrCerereOferta,DataCerereOferta,IDModTransCerereOferta,ObservatiiCerereOferta)" + _
" VALUES (#IDFurnizor,#NrCerereOferta,#DataCerereOferta,#IDModTransCerereOferta,#ObservatiiCerereOferta);" + _
" SELECT SCOPE_IDENTITY();"
cmdInsertCerereOferta.Parameters.Add("#IDFurnizor", SqlDbType.Int).Value = CInt(Me.t_IDFurnizor.Text)
cmdInsertCerereOferta.Parameters.Add("#NrCerereOferta", SqlDbType.Int).Value = CInt(Me.t_NumarCerereOferta.Text)
cmdInsertCerereOferta.Parameters.Add("#DataCerereOferta", SqlDbType.Date).Value = CDate(Me.t_DataCerereOferta.Text)
cmdInsertCerereOferta.Parameters.Add("#IDModTransCerereOferta", SqlDbType.Int).Value = 1
cmdInsertCerereOferta.Parameters.Add("#ObservatiiCerereOferta", SqlDbType.NVarChar).Value = Me.t_ObservatiiCerereOferta.Text
Dim IDCerereOferta As Integer = cmdInsertCerereOferta.ExecuteScalar
Dim ListaPieseCerereOferta = Me.CerereOfertaDataSet.ListaPieseCerereOferta.AsEnumerable
Dim ListaNecesarePePiesa = Me.CerereOfertaDataSet.NecesarePeOferta.AsEnumerable
Dim PieseOferta = From q In ListaPieseCerereOferta _
Select q
Dim cantTotalaPiese = Aggregate q In ListaPieseCerereOferta _
Into Sum(q.Cantitate)
Dim salvat As Integer = 0
Dim curIDPiesaDeSchimb As Integer
For Each piesa In PieseOferta
curIDPiesaDeSchimb = piesa.IDPiesaDeSchimb
Dim NecesarePePiesa = From p In ListaNecesarePePiesa _
Select p _
Order By p.IDNecesar Descending
Dim curIDNecesar As Integer
For Each necesar In NecesarePePiesa
curIDNecesar = necesar.IDNecesar
Dim cmdInsertPiesaCerereOferta As SqlCommand = conn.CreateCommand
cmdInsertPiesaCerereOferta.Transaction = sqlTrans
cmdInsertPiesaCerereOferta.CommandText = "INSERT INTO CereriOferte (IDCerereOferta,IDPiesaDeSchimb,Cantitate,UM,Observatii)" + _
" VALUES (#IDCerereOferta,#IDPiesaDeSchimb,#Cantitate,#UM,#Observatii);" + _
" SELECT SCOPE_IDENTITY();"
cmdInsertPiesaCerereOferta.Parameters.Add("#IDCerereOferta", SqlDbType.Int)
cmdInsertPiesaCerereOferta.Parameters.Add("#IDPiesaDeSchimb", SqlDbType.Int)
cmdInsertPiesaCerereOferta.Parameters.Add("#Cantitate", SqlDbType.Float)
cmdInsertPiesaCerereOferta.Parameters.Add("#UM", SqlDbType.NVarChar)
cmdInsertPiesaCerereOferta.Parameters.Add("#Observatii", SqlDbType.NVarChar)
Dim cmdInsertNecesarCerereOferta As SqlCommand = conn.CreateCommand
cmdInsertNecesarCerereOferta.Transaction = sqlTrans
cmdInsertNecesarCerereOferta.CommandText = "INSERT INTO NecesareCereriOferte (IDPiesaNecesar,IDPiesaCerereOferta)" + _
" VALUES (#IDPiesaNecesar,#IDPiesaCerereOferta)"
cmdInsertNecesarCerereOferta.Parameters.Add("#IDPiesaNecesar", SqlDbType.Int)
cmdInsertNecesarCerereOferta.Parameters.Add("#IDPiesaCerereOferta", SqlDbType.Int)
Select Case curIDNecesar
Case 0
cmdInsertPiesaCerereOferta.Parameters("#IDCerereOferta").Value = IDCerereOferta
cmdInsertPiesaCerereOferta.Parameters("#IDPiesaDeSchimb").Value = curIDPiesaDeSchimb
cmdInsertPiesaCerereOferta.Parameters("#Cantitate").Value = 1
cmdInsertPiesaCerereOferta.Parameters("#UM").Value = piesa.UM
cmdInsertPiesaCerereOferta.Parameters("#Observatii").Value = ""
For i = 1 To necesar.Cantitate
cmdInsertPiesaCerereOferta.ExecuteNonQuery()
salvat += 1
Me.tsspb_SalvareCerereOferta.Value = CInt(100 * salvat / cantTotalaPiese)
Next
Case Is > 0
Me.PieseNecesarePeOfertaTableAdapter.Fill(Me.CerereOfertaDataSet.PieseNecesarePeOferta, curIDNecesar, curIDPiesaDeSchimb, CInt(necesar.Cantitate))
Dim ListaPieseNecesarePeOferta = Me.CerereOfertaDataSet.PieseNecesarePeOferta.AsEnumerable
Dim PieseNecesareOferta = From q In ListaPieseNecesarePeOferta _
Select q
For i = 1 To necesar.Cantitate
cmdInsertPiesaCerereOferta.Parameters("#IDCerereOferta").Value = IDCerereOferta
cmdInsertPiesaCerereOferta.Parameters("#IDPiesaDeSchimb").Value = curIDPiesaDeSchimb
cmdInsertPiesaCerereOferta.Parameters("#Cantitate").Value = 1
cmdInsertPiesaCerereOferta.Parameters("#UM").Value = piesa.UM
cmdInsertPiesaCerereOferta.Parameters("#Observatii").Value = ""
Dim insertedIDPiesaCerereOferta As Integer = cmdInsertPiesaCerereOferta.ExecuteScalar
cmdInsertNecesarCerereOferta.Parameters("#IDPiesaNecesar").Value = PieseNecesareOferta(i - 1).IDPiesaNecesar
cmdInsertNecesarCerereOferta.Parameters("#IDPiesaCerereOferta").Value = insertedIDPiesaCerereOferta
cmdInsertNecesarCerereOferta.ExecuteNonQuery()
salvat += 1
Me.tsspb_SalvareCerereOferta.Value = CInt(100 * salvat / cantTotalaPiese)
Next
End Select
Next
Next
sqlTrans.Commit()
MsgBox("Cererea de oferta a fost salvata.")
Catch ex As Exception
Try
sqlTrans.Rollback()
MsgBox("A aparut o eroare." + vbNewLine + ex.ToString + vbNewLine + "RollBack success. Cererea nu a fost salvata.")
Catch ex2 As SqlException
If Not sqlTrans.Connection Is Nothing Then
MsgBox("An exception of type " & ex2.GetType().ToString() & _
" was encountered while attempting to roll back the transaction.")
End If
End Try
Finally
If conn.State = ConnectionState.Open Then conn.Close()
End Try
Else
MsgBox("Nu ai completat integral cererea de oferta!")
End If
End Sub
query that locks:
SELECT TOP (100) PERCENT dbo.qry_NecesareNerezolvate.IDPiesaNecesar, COUNT(dbo.NecesareCereriOferte.IDPiesaCerereOferta) AS CereriOferte,
dbo.qry_NecesareNerezolvate.IDNecesar, dbo.qry_NecesareNerezolvate.IDPiesaDeSchimb, dbo.qry_NecesareNerezolvate.Cantitate
FROM dbo.qry_NecesareNerezolvate LEFT OUTER JOIN
dbo.NecesareCereriOferte ON dbo.qry_NecesareNerezolvate.IDPiesaNecesar = dbo.NecesareCereriOferte.IDPiesaNecesar
GROUP BY dbo.qry_NecesareNerezolvate.IDPiesaNecesar, dbo.qry_NecesareNerezolvate.IDNecesar, dbo.qry_NecesareNerezolvate.IDPiesaDeSchimb,
dbo.qry_NecesareNerezolvate.Cantitate
qry_NecesareNerezolvate:
SELECT TOP (100) PERCENT dbo.Necesare.IDPiesaNecesar, dbo.Necesare.IDNecesar, dbo.Necesare.IDPiesaDeSchimb, dbo.Necesare.Cantitate, dbo.Necesare.UM,
dbo.Necesare.Observatii
FROM dbo.Necesare LEFT OUTER JOIN
dbo.qry_NecesareComandateRezolvate ON dbo.Necesare.IDPiesaNecesar = dbo.qry_NecesareComandateRezolvate.IDPiesaNecesar
WHERE (dbo.qry_NecesareComandateRezolvate.IDPiesaNecesar IS NULL)
qry_NecesareComandateRezolvate:
SELECT dbo.Necesare.IDPiesaNecesar, dbo.NecesareComenzi.IDPiesaComanda, dbo.NecesareRezolvate.IDBonTransfer
FROM dbo.Necesare LEFT OUTER JOIN
dbo.NecesareComenzi ON dbo.Necesare.IDPiesaNecesar = dbo.NecesareComenzi.IDPiesaNecesar LEFT OUTER JOIN
dbo.NecesareRezolvate ON dbo.Necesare.IDPiesaNecesar = dbo.NecesareRezolvate.IDPiesaNecesar
WHERE (dbo.NecesareComenzi.IDPiesaComanda IS NOT NULL) OR
(dbo.NecesareRezolvate.IDBonTransfer IS NOT NULL)
for i=1: insert, select then insert is working
then i=2 and: INSERT into table2... is working but SELECT FROM table1 and table3... gets timeout...
I don't understand why!
PS: If I break the code before second run of SELECT FROM table3 then go to SSMS and run the select query it gets timeout too...
In your code sample below, you have the transaction open till the end of the For Loop.
It seems to me that when i =1 , the transaction gets opened and a insertion is made. Now when i=2 , the to be inserted row when i=1 is in uncomitted state and if your select is joining to the table1 the lock level would have escalated to table level and locked everything down. Move the commit to inside the for loop and check how it goes.
for i=1 to x
...
INSERT into table2
...
SELECT FROM table3
...
INSERT into table3
...
next i
sqltransaction.commit

passing parameters into stored procedures classic asp

I've asked a similar question before and although I've attempted to fix my previous code i now end up with an error "Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another". I want to pass a single character as a parameter to query a database then use recordset to print out to a webpage. My classic asp code is below
Set objCon = CreateObject("ADODB.Connection")
Set objRS = CreateObject("ADODB.Recordset")
set objComm = CreateObject("ADODB.Command")
objCon.ConnectionString = "Provider=SQLOLEDB.1;Password=xxxx;Persist Security Info=True;User ID=xxxx;Initial Catalog=Movies;Data Source=xxxx-PC"
objCon.open objCon.ConnectionString
objComm.ActiveConnection = objCon.ConnectionString
objComm.CommandText = "Paging_Movies"
objComm.CommandType = adCmdStoredProc
Set objParameter = objComm.CreateParameter
objParameter.Name = "alphaChar"
objParameter.Type = adChar
objParameter.Direction = adParamInput
objParameter.Value = "a"
objComm.Parameters.Append objParameter
set objRs = objComm.Execute
Also my stored procedure is below -
CREATE PROCEDURE Paging_Movies
#alphaChar char(1)
AS
if #alphaChar = '#'
select * from Movies where movies like '[^a-z]%'
else
select * from Movies where movies like #alphaChar + '%'
Perhaps you're adding the parameter twice. Try to replace:
objComm.ActiveConnection = objCon.ConnectionString
objComm.CommandText = "Paging_Movies"
objComm.CommandType = adCmdStoredProc
Set objParameter = objComm.CreateParameter
objParameter.Name = "alphaChar"
objParameter.Type = adChar
objParameter.Direction = adParamInput
objParameter.Value = "a"
Set objParameter = objCommand.CreateParameter ("alphaChar", adChar, _
adParamInput, "a")
objComm.Parameters.Append objParameter
with just:
objCommand.CreateParameter ("alphaChar", 129, 1, 1, "a")
Edited as your comment suggests to use the numeric values for adChar (129) and adParamInput (1) from the W3Schools CreateParameter page.