How i put multiple values in procedure while in? vb.net [duplicate] - sql-server

This question already has answers here:
Parameterize an SQL IN clause
(41 answers)
Closed 7 years ago.
I have code in vb.net with #values like this:
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con = FunctionConnection()
cmd.Connection = con
cmd.CommandText = "GetVerification"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#Value", "1,2,3,4")
Dim Header_DataReader As SqlDataReader = Nothing
con.Open()
Header_DataReader = cmd.ExecuteReader
And my procedure like that:
ALTER PROCEDURE GetVerification (#Value varchar(255))
as
BEGIN
SELECT id, ControlPlanID, ParagraphID, ParagraphOrder, Specification, SpecificationParagraph, Dimension, Description, Samples, Frequency, ActivityResource,
ActivityName, Observation, RequrementNom, RequrementPlus, RequrementMinus, Units
FROM CP_Sequence
WHERE (ParagraphOrder IN (#Value))
End
How put multilple values in my procedure, i want to put in #values 1,2,3,4 for 4 different rows for database
if i put in Sql code like this work but not for my procedure:
SELECT id, ControlPlanID, ParagraphID, ParagraphOrder, Specification, SpecificationParagraph, Dimension, Description, Samples, Frequency, ActivityResource,
ActivityName, Observation, RequrementNom, RequrementPlus, RequrementMinus, Units
FROM CP_Sequence
WHERE (ParagraphOrder IN (1, 2, 3, 4))
Thanks a lot

ALTER PROCEDURE dbo.GetVerification (#Value VARCHAR(255))
AS
BEGIN
SET NOCOUNT ON
DECLARE #a TABLE (ID INT PRIMARY KEY WITH (IGNORE_DUP_KEY=ON))
INSERT INTO #a
SELECT t.c.value('.', 'INT')
FROM (SELECT x = CAST('<t>' + REPLACE(#Value, ',', '</t><t>') + '</t>' AS XML)) r
CROSS APPLY r.x.nodes('/t') t(c)
SELECT *
FROM dbo.CP_Sequence
WHERE ParagraphOrder IN (SELECT * FROM #a)
OPTION(RECOMPILE)
END

Related

Returning values from a stored procedure ASP Classic [duplicate]

This question already has an answer here:
operation not allowed when the object is closed when running more advanced query
(1 answer)
Closed 1 year ago.
I am having a problem to output the results from a stored procedure using SQL Server and ASP Classic. If I have a simple SELECT into the procedure, it works fine. But with the code shown here, I get an error.
I have this stored procedure in SQL Server:
ALTER PROCEDURE [dbo].[Sp_Teste]
#data varchar(8)
AS
BEGIN
--DROP TABLE IF EXISTS #TempSubs
DECLARE #TempSubs TABLE
(
PedidoID Int,
NumeroPedido Varchar(20),
SubstituidoPor Varchar(8000)
)
INSERT INTO #TempSubs (PedidoID, NumeroPedido, SubstituidoPor)
SELECT
P.ID, P.NumeroPedido,
STRING_AGG(CAST(IPA.Quantidade AS varchar(5)) + 'X ' + Pd.Nome, ', ') + ' por ' + STRING_AGG(CAST(IPA.Quantidade AS varchar(5)) + 'X ' + Pd2.Nome, ', ') AS SubstituidoPor
FROM
Pedidos P, Clientes C, Produtos Pd, ItensPedidosAjustado IPA, Produtos Pd2
WHERE
P.ID = IPA.PedidoId
AND P.ClienteId = C.ID
AND Pd.ID = IPA.ProdutoId
AND Faltante = 1
AND CONVERT(Date, P.DataPedido, 103) = CONVERT(Date, #data, 103)
AND (IPA.ProdutoSubstituidoId <> 0)
AND Pd2.ID = IPA.ProdutoSubstituidoId
AND ((P.StatusPedido <> 'Pause' AND P.StatusPedido <> 'PULOU ENTREGA' AND P.StatusPedido <> 'Pedido Cancelado') OR P.StatusPedido IS NULL)
GROUP BY
P.ID, P.NumeroPedido, IPA.ProdutoSubstituidoId
SELECT
(SELECT STRING_AGG(Indisponibilidade, ', ')
FROM #TempIndis A
WHERE A.PedidoID = P.ID) AS Indisponibilidade,
(SELECT STRING_AGG(SubstituidoPor, ', ')
FROM #TempSubs A
WHERE A.PedidoID = P.ID) AS Substituicao
FROM
Pedidos P, Clientes C, ItensPedidosAjustado IPA
WHERE
P.ID = IPA.PedidoId
AND P.ClienteId = C.ID
AND Faltante = 1
AND CONVERT(Date, P.DataPedido, 103) = CONVERT(Date, #data, 103)
AND ((P.StatusPedido <> 'Pause' AND P.StatusPedido <> 'PULOU ENTREGA' AND P.StatusPedido <> 'Pedido Cancelado') OR P.StatusPedido IS NULL)
AND P.PedidoCancelado = 0
GROUP BY
P.ID, P.NumeroPedido, C.Nome, C.Email, P.TipoAssinatura
ORDER BY
numeropedido
END
and this code in ASP Classic
db_conn = "Provider=SQLNCLI11;Server=xxxx;Database=BaseGaia;Uid=sqlserver;Pwd=xxxxx;"
set conn = server.createobject("adodb.connection")
set Cmd = Server.CreateObject("ADODB.Command")
'-------------------------------------------------------
conn.open (db_conn)
'-------------------------------------------------------
set rs = Server.CreateObject("ADODB.RecordSet")
sSQL = "EXEC Sp_Teste #data = '20210301'"
set rs = conn.execute (sSQL)
response.write rs.eof
I get this error:
ADODB.Recordset error '800a0e78'
Operation is not allowed when the object is closed.
/Atendimento/testestoreprocedure.asp, line 18
By default, SQL Server returns DONE_IN_PROC (rowcount) messages after INSERT statements, which ADO classic returns a closed/empty result sets. These must be consumed by invoking the NextRecordset method before the SELECT query results are available.
To avoid the extra coding, make a habit of specifying SET NOCOUNT ON; in stored procedures to suppress those unwanted results. Add that to the beginning of the proc code to avoid the error.

Executing INSERT from Identity column Output in VB.NET

Using VB.NET and SQL Server: I have a table [Item_List]. When I add a new item from a Windows form, I want to insert the record into the Item_List table, get the ItemID which is an IDENTITY, and use that to insert a corresponding record into the financial tracking [Inventory_Transactions] table.
I tested the following query directly in a T-SQL query window with success:
DECLARE #OutputTbl TABLE (ItemID INT);
INSERT INTO [Item_List] (Item_Name, Vendor, Quantity, Price, Category, Active, Notes, Created)
OUTPUT INSERTED.ItemID INTO #OutputTbl(ItemID)
VALUES ('Test Item', 'Walmart', 42, 4.22, 'Stuff', 1, '', CURRENT_TIMESTAMP);
INSERT INTO Inventory_Transactions (TransDate, Category, Transactee, Amount, Item, Quantity, Description)
SELECT
CURRENT_TIMESTAMP, 'Stuff', 'Walmart', -4.22, ItemID, 42, '';
However when I try to run using ExecuteNonQuery() I get an error
Invalid column name 'ItemID'
I've used the exact script from above and also below with parameters - same error.
Dim sql As String = "DECLARE #OutputTbl TABLE (ItemID INT); " &
"INSERT INTO [Item_List] (Item_Name, Vendor, Quantity, Price, Category, Active, Notes, Created) " &
"OUTPUT INSERTED.ItemID INTO #OutputTbl(ItemID) " &
"VALUES (#ItemName, #Vendor, #Quantity, #Price, #Category, #Active, #Notes, CURRENT_TIMESTAMP); " &
"INSERT INTO Inventory_Transactions (TransDate, Category, Transactee, Amount, Item, Quantity, Description) " &
"SELECT CURRENT_TIMESTAMP, #Category, #Vendor, '-' + #Price, ItemID, #Quantity, #Notes;"
Using conn As New SqlConnection(My.Settings.dbConnectionString)
Dim cmd As New SqlCommand(sql, conn)
If Not IsNothing(params) Then
For Each param In params
cmd.Parameters.Add(param)
Next
End If
If cmd.Connection.State <> ConnectionState.Open Then
cmd.Connection.Open()
Dim rows As Integer = cmd.ExecuteNonQuery()
End Using
How can I implement this in VB?
I just tested this code and it worked exactly as expected:
Dim sql = "INSERT INTO Parent (ParentName) VALUES (#ParentName);
INSERT INTO Child (ChildName, ParentId) VALUES (#ChildName, SCOPE_IDENTITY())"
command.CommandText = sql
command.Parameters.Add("#ParentName", SqlDbType.NVarChar, 50).Value = "Parent1"
command.Parameters.Add("#ChildName", SqlDbType.NVarChar, 50).Value = "Child1"
command.ExecuteNonQuery()
The SCOPE_IDENTITY function gets the last identity value generated in the current scope.
If you need to use the identity value multiple times then you can assign it to a parameter and use that, e.g.
Dim sql = "INSERT INTO Parent (ParentName) VALUES (#ParentName);
SELECT #ParentId = SCOPE_IDENTITY();
INSERT INTO Child (ChildName, ParentId) VALUES (#ChildName, #ParentId)"
command.CommandText = sql
command.Parameters.Add("#ParentName", SqlDbType.NVarChar, 50).Value = "Parent1"
command.Parameters.Add("#ParentId", SqlDbType.Int).Direction = ParameterDirection.Output
command.Parameters.Add("#ChildName", SqlDbType.NVarChar, 50).Value = "Child1"
command.ExecuteNonQuery()
If you need to use the identity value in your VB code then also use a parameter like this:
Dim parentSql = "INSERT INTO Parent (ParentName) VALUES (#ParentName);
SELECT #ParentId = SCOPE_IDENTITY();"
parentCommand.CommandText = parentSql
parentCommand.Parameters.Add("#ParentName", SqlDbType.NVarChar, 50).Value = "Parent1"
parentCommand.Parameters.Add("#ParentId", SqlDbType.Int).Direction = ParameterDirection.Output
parentCommand.ExecuteNonQuery()
Dim childSql = "INSERT INTO Child (ChildName, ParentId) VALUES (#ChildName, #ParentId)"
childCommand.CommandText = childSql
childCommand.Parameters.Add("#ChildName", SqlDbType.NVarChar, 50).Value = "Child1"
childCommand.Parameters.Add("#ParentId", SqlDbType.Int).Value = parentCommand.Parameters("#ParentId").Value
childCommand.ExecuteNonQuery()
I think this:
"SELECT CURRENT_TIMESTAMP, #Category, #Vendor, '-' + #Price, ItemID, #Quantity, #Notes;"
should be:
"SELECT CURRENT_TIMESTAMP, #Category, #Vendor, '-' + #Price, ItemID, #Quantity, #Notes from #OutputTbl;"

Best practice to pass a list as input in SQL query using vb.net [duplicate]

This question already has answers here:
Pass table valued parameter using ADO.NET
(5 answers)
Pass Array Parameter in SqlCommand
(11 answers)
Closed 5 years ago.
I am using vb.net with a SQL Server 2012 database.
I want to check the status of a list of files in the databases. The query is simple and something like this.
DECLARE #Filename NVARCHAR(100)
SET #Filename = 'MyFileName.doc'
SELECT DISTINCT
Docs.Filename,
Status.Name as 'Status'
FROM
[Documents] AS Docs
INNER JOIN
[Status] AS Status ON Status.StatusID = Docs.CurrentStatusID
WHERE
Docs.Filename LIKE #Filename
It works fine for one filename and I can launch it easily in vb.net using a sql connection as in this example.
Dim conn As New SqlConnection
If conn.State = ConnectionState.Closed Then
conn.ConnectionString = PDMConnectionString
End If
Try
conn.Open()
Dim sqlquery As String =
"DECLARE #Filename NVARCHAR(100)
SELECT DISTINCT
Docs.Filename,
Status.Name as 'Status'
FROM [Documents] AS Docs
INNER JOIN [Status] AS Status
ON Status.StatusID = Docs.CurrentStatusID
WHERE Docs.Filename LIKE #Filename "
Dim data As SqlDataReader
Dim adapter As New SqlDataAdapter
Dim parameter As New SqlParameter
Dim command As SqlCommand = New SqlCommand(sqlquery, conn)
With command.Parameters
.Add(New SqlParameter("#filename", "MyFileName.doc"))
End With
command.Connection = conn
adapter.SelectCommand = command
data = command.ExecuteReader()
While data.Read
'do something'
End While
Catch ex As Exception
End Try
The problem is that I need to find the status of a lot of files and I would like to do it with only one query.
I can do it directly in the query by by changing the last line like this, removing the parameter in vb.net and sending directly the query:
WHERE
Docs.Filename IN ('MyFileName.doc', 'MyOtherFileName.doc')
But it implies a lot of string concatenation and I don't really like how the code looks like with that solution.
What is the best practice to use in that type of situation in order to use less string concatenation and to make a code that is easier to manage?
You could use a function to take a comma separated string and return a table...
CREATE FUNCTION [dbo].[FileNames]( #FilenameValues nvarchar(max) )
RETURNS #Result TABLE( FileName nvarchar(max) )
AS
BEGIN
-- convert to an xml string
DECLARE #xml XML
SELECT #xml = CAST( '<A>' + REPLACE( #FilenameValues, ',', '</A><A>' ) + '</A>' AS XML )
-- select rows out of the xml string
INSERT INTO #Result
SELECT DISTINCT LTRIM( RTRIM( t.value( '.', 'nvarchar(max)' ) ) ) AS [FileName]
FROM #xml.nodes( '/A ') AS x(t)
RETURN
END
Then in your SQL either JOIN to it ...
JOIN (
SELECT * FROM dbo.FileNames( 'MyFileName.doc, MyOtherFileName.doc' )
) FileNames ON FileNames.FileName = Docs.Filename
OR use in a WHERE ...
WHERE Docs.Filename IN(
SELECT * FROM dbo.FileNames( 'MyFileName.doc, MyOtherFileName.doc' )
)

incrementing by 1 in vb10 connected to sql edited

i want to have an student id with last 2 digits of the year and a string of -001 example 13-001 and read the last value in the table example 13-002 is the last value in the table how it can becomes 13-003 when the forms load. i have a value on table 13-001 and i had been try this code but it gives me 14 instead 13-002
Dim dr As SqlDataReader
Dim Cmd As New SqlCommand
con.Open()
With Cmd
.Connection = con
.CommandText = "SELECT * FROM tbl_student ORDER BY Student_no DESC"
End With
dr = Cmd.ExecuteReader
If dr.Read Then
lblstudno.Text = Val(dr.Item(0)) + 1
End If
con.Close()
thanks hope you understand
INSERT INTO
students
( student_id ) VALUES
(
CAST( ( YEAR( GETDATE() ) % 100 ) + 1 AS varchar(2) ) + '-' +
CAST(
SELECT TOP 1
CAST( RIGHT( student_id, 3 ) AS int ) + 1
FROM
students
ORDER BY
student_id DESC
AS varchar(3) )
)
Note that this will fail if you reach 999 students. There is also a potential race condition unless you do a lock of some kind on the table (see transaction isolation).
My post also demonstrates why IDENTITY keys are generally a good idea instead of rolling your own (assuming you want to use this system as your primary key).

How to select output scalar values in sql server?

Hi I'm still new in TSQL. How can I output Scalar variables so that my vb code can access it?
in VB I use the rs method. In this case I will have to create 3 rs to be be able to access the data below. I would like to have a stored proc that can give me the 4 values I need without using multiple rs.
Create PROCEDURE [dbo].[sp_tblTransaction_GET_All_Totals]
#TransID bigint
AS
Declare #MyTotalCharges as money
Declare #MyTotalDiscounts as money
Declare #MyTotalPayments as money
Declare #TotalCharges as money
Declare #TotalDiscounts as money
Declare #TotalPayments as money
Declare #Balance as money
SELECT #MyTotalCharges = SUM(Amount)
FROM tblTransactionDetails
WHERE (TransID = #TransID)
SELECT #MyTotalDiscounts = SUM(Amount)
FROM tblTransaction_DP
WHERE (TransID = #TransID)
SELECT #MyTotalPayments = SUM(Amount)
FROM tblPayments
WHERE (TransID = #TransID)
--Below are the scalar values I need to be ouputed and accessed by my vb app.
--How can I output the values below?
#TotalCharges = #MyTotalCharges
#TotalDiscounts = #MyTotalDiscounts
#TotalPayments = #MyTotalPayments
#Balance = (#MyTotalCharges - #MyTotalDiscounts - #MyTotalPayments)
You need to return the values from the stored procedure as a table. Add this to your procedure.
SELECT
#TotalCharges as [Total Charges],
#TotalDiscounts as [Total Discounts],
#TotalPayments as [TotalPayments],
#Balance as [Balance]
Then you can execute the stored procedure from your VB app and load the table into a DataTable.
int transactionID = 0;
DataTable table = new DataTable();
using (var connection = new SqlConnection("connectionString")
using (var command = new SqlCommand("sp_tblTransaction_GET_All_Totals", connection)
{
connection.Open();
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#TransID", transactionID);
using (var adapter = new SqlDataAdapter(command))
{
adapter.Fill(table);
}
}
calling a stored procedure from C# using SqlDataAdapter
Here's the documentation on SqlDataAdapter, which will include examples in both C# and VB.
MSDN - SqlDataAdapter Class (System.Data.SqlClient)
Have you tried?
SELECT #Balance AS 'Balance', #TotalCharges AS 'TotalCharges' ...

Resources