Executing INSERT from Identity column Output in VB.NET - sql-server

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;"

Related

In VB.NET, who can Iet all databases that contain a specific table

In VB.NET am trying to return all databases that have a specific table. The code I have been using polls just the databases and that works fine. When I add the CASE statement below to get just the ones with the table I need then it returns nothing.
strQuery = "SELECT [name] FROM sys.databases where create_date > '2016-07-01' and [name] not like '_Config_Options' order by create_date desc"
sqlCon = New SqlConnection(strConn)
Using (sqlCon)
Dim sqlComm As SqlCommand = New SqlCommand(strQuery, sqlCon)
sqlCon.Open()
Dim sqlReader As SqlDataReader = sqlComm.ExecuteReader
If sqlReader.HasRows Then
While (sqlReader.Read())
cmbDatabase.Items.Add(sqlReader.GetString(0))
End While
End If
sqlReader.Close()
End Using
The above code returns the full list of databases.
When I change the strQuery to
strQuery = "SELECT [name] FROM sys.databases WHERE CASE WHEN state_desc = ''ONLINE'' THEN OBJECT_ID(QUOTENAME([name]) + ''.[dbo].[MyTable]'', ''U'') END IS NOT NULL order by create_date desc"
I get nothing back. After executing Dim sqlReader As SqlDataReader = sqlComm.ExecuteReader, the code jumps to the End Using. I don't see an error code.
Joel Coehoom gets the credit for answering. I removed the double single quotes and it works.
strQuery = "SELECT [name] FROM sys.databases WHERE CASE WHEN state_desc = 'ONLINE' THEN OBJECT_ID(QUOTENAME([name]) + '.[dbo].[MyTable]', 'U') END IS NOT NULL order by create_date desc"

I am gettin a null error in the code below for one user

The function below is trying to get the earliest date from a table with 3 dates, one for each type of user, care, sales and manager. This is to build up the diary system by first finding the first date in the diary dates. It's working for some users, but in one case the values do not return at and it gives null.
Private Function GetEarliestDate() As Date
Dim strSQL As String
Dim cmd As New SqlCommand
Dim dDate As Date
Try
strSQL = "Select dT.RecordID, MIN(dT.inDate) As [EarliestDate]
FROM (
Select RecordID, SentDate As [inDate]
From tblOrderDetails Where Flagged = 0 AND SalesID = '" & gUserID & "'
UNION ALL
Select RecordID, DiaryDate AS [inDate]
From tblOrderDetails
Where Flagged=0 And ManID ='" & gUserID & "'
UNION ALL
Select RecordID, CareDate As [inDate]
From tblOrderDetails
Where Flagged = 0 And CareID ='" & gUserID & "'
) As dT Group By RecordID"
cmd.CommandText = strSQL
cmd.Connection = CnMaster
cmd.CommandType = CommandType.Text
Dim RecordCount As Integer
RecordCount = 0
dDate = DateTime.MaxValue
Using reader As SqlDataReader = cmd.ExecuteReader()
While (reader.Read())
RecordCount += 1
Dim dt As DateTime = reader.GetDateTime(1)
If dt < dDate Then
dDate = dt
End If
End While
If dDate = DateTime.MaxValue Then
dDate = DateTime.MinValue
End If
End Using
cmd.Dispose()
Return dDate
Catch ex As Exception
Error_Handler(ex, "GetEarliestDate", "Unable to Get The Earliest Date!")
End Try
Put in all 3 queries additional where:
where SentDate is not null ...
where DiaryDate is not null ...
where CareDate is not null ...

I am trying to insert values into a table from multiple tables (table relationships are shown)

I have four tables. The purpose of this code is for user to select a customer from a combobox and the check the shipments going to that customer to put into the FormHeaderTable. Let's pretend two shipments get selected.... forms can have several Shipments. Shipments can have several partnumbers
Table 1: FormHeaderTable
FormID (pk)
OrderKey(pk) (keeps track of how many forms have been made for a specific customer)
CreationDate
CustomerName
Table 2: FormLineTable
LineID (pk)
FormID, (pk, fk) (comes from FormHeaderTable)
OrderKey (pk, fk) (comes from FormHeaderTable)
ShipmentNumber (pk, fk) (comes from ShipmentHeaderTable)
PartNumber
Table 3: ShipmentHeaderTable
ShipmentNumber (pk) (rest of columns not needed for this question, just shipment details)
Table4: ShipmentLineTable
ShipmentLine (PK)
ShipmentNumber(PK, FK) (comes from shipmentHeaderTable)
PartNumber
I need to insert values into my FormLineTable based on the ShipmentNumbers selected from a checklistbox that is populated by a customer combobox's selection.
I tried to do this:
Dim OrderKey As Integer
Dim LastFormID As Integer
Dim NextFormID As Integer
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Get FormID and Get OrderKey
Dim MAXOrderKey As String = "SELECT MAX(OrderKey) FROM FormHeaderTable WHERE CustomerName = #CustomerName"
Dim MAXOrderKeyCommand As New SqlCommand(MAXOrderKey, con)
Dim MAXFormID As String = "Select MAX(FormID) FROM FormHeaderTable"
Dim MAXFormIDCommand As New SqlCommand(MAXFormID, con)
MAXOrderKeyCommand.Parameters.Add("#CustomerName", SqlDbType.VarChar).Value = cboCustomer.Text
If con.State = ConnectionState.Closed Then con.Open()
Try
LastFormID = CInt(MAXFormIDCommand.ExecuteScalar)
Catch ex As System.Exception
LastFormID = 0
End Try
Try
OrderKey = CInt(MAXOrderKeyCommand.ExecuteScalar)
Catch ex As System.Exception
OrderKey = 0
End Try
con.Close()
NextFormID = LastFormID + 1
OrderKey = OrderKey + 1
Dim cmd As New SqlCommand("SET IDENTITY_INSERT FormHeadertable ON Insert INTO FormHeaderTable (FormID, CustomerName, CreationDate, OrderKey) Values (#FormID, #CustomerName, #CreationDate, #OrderKey) SET IDENTITY_INSERT FormHeadertable OFF ", con)
cmd.Parameters.Add("#FormID", SqlDbType.Int).Value = NextFormID
cmd.Parameters.Add("#CustomerName", SqlDbType.VarChar).Value = cboCustomer.Text
cmd.Parameters.Add("#CreationDate", SqlDbType.Date).Value = Date.Now()
cmd.Parameters.Add("#OrderKey", SqlDbType.Int).Value = OrderKey
'this is where I need help'
Dim cmd1 As New SqlCommand("Insert into FormLineTable (FormID, OrderKey, LineId, ShipmentNumber, PartNumber) Select FormID, OrderKey, ShipmentLineNumber, ShipmentNumber, PartNumber FROM ShipmentLineTable CROSS JOIN FormHeaderTable", con)
cmd1.Parameters.Add("#FormID", SqlDbType.Int).Value = NextFormID
cmd1.Parameters.Add("#OrderKey", SqlDbType.Int).Value = OrderKey
Dim isFirst As Boolean = True
For i As Integer = 0 To chkLstShipments.Items.Count - 1
If chkLstShipments.GetItemCheckState(i) = CheckState.Checked Then
If isFirst = True Then
cmd1.CommandText += " WHERE ShipmentNumber = #ShipmentNumber" + i.ToString
isFirst = False
Else
cmd1.CommandText += " OR ShipmentNumber = #ShipmentNumber" + i.ToString
End If
cmd1.Parameters.Add("#ShipmentNumber" + i.ToString, SqlDbType.Int).Value = chkLstShipments.Items(i)
End If
Next
If con.State = ConnectionState.Closed Then con.Open()
cmd.ExecuteNonQuery()
cmd1.ExecuteNonQuery()
con.Close()
End Sub
My error
36 duplicate values or so...
Got rid of cross join section. switched FormId and OrderKey to the variables #FormId and #OrderKey and filled in these two variables with the variables I defined earlier in the code: NextNaftaId and OrderKey
New code looks like this:
Dim cmd1 As New SqlCommand("Insert into FormLineTable (FormID, OrderKey, LineId, ShipmentNumber, PartNumber) Select #FormID, #OrderKey, ShipmentLineNumber, ShipmentNumber, PartNumber FROM ShipmentLineTable", con)
cmd1.Parameters.Add("#FormID", SqlDbType.Int).Value = NextFormID
cmd1.Parameters.Add("#OrderKey", SqlDbType.Int).Value = OrderKey

Insert multiple rows, count based on another table columns

I have 3 Tables. Item, StockDetail, Branch
I want to INSERT 2 of them at once. The Item and StockDetail table.
Item has 3 columns = ItemID, Title, Price.
StockDetail has 3 columns = ItemID, BranchID, Stock.
Branch has 1 column = BranchID.
In this code below, INSERT into Item works fine, but not for StockDetail table, it doesn't INSERT anything!
Now for the StockDetail if it works, I want to insert it with the condition below:
If you add an item, then it'll add this item with all existed BranchID.
That mean, every Branches will have this item.
e.g:
You add an item, while
Branch has 3 rows of BranchID = BR000, BR001, BR002.
It will insert to StockDetail with 3 rows as well, at once (single Query)
Complete result of StockDetail (single Query):
ItemID | BranchID | Stock
______________________________
IM000 | BR000 | 0
IM000 | BR001 | 0
IM000 | BR002 | 0
The Code:
'Add function'
'Insert to StockDetail'
Dim theCommand As New SqlCommand
Dim theDataAdapter As New SqlDataAdapter
Dim theDataTable As New DataTable
theCommand.Connection = theConnection
theCommand.CommandText = "INSERT INTO StockDetail VALUES(
'" & Me.TextBox_ItemID.Text & "',
SELECT COUNT(BranchID) FROM Branch,
'0'
)"
theDataAdapter.SelectCommand = theCommand
'Insert to Item'
theCommand.Connection = theConnection
theCommand.CommandText = "INSERT INTO Item VALUES('" & Me.TextBox_ItemID.Text & "', '" & Me.TextBox_Title.Text & "', '" & Me.TextBox_Price.Text & "')"
theDataAdapter.SelectCommand = theCommand
theDataAdapter.Fill(theDataTable)
DataGridView_Item.DataSource = theDataTable
theCommand.Dispose()
theDataAdapter.Dispose()
UPDATE:
The code below will tell you the working multiple INSERT, but not with the BranchID INSERT.
'Insert to StockDetail'
theConnection.Open()
Dim theCommand As New SqlCommand
Dim theDataAdapter As New SqlDataAdapter
theCommand.Connection = theConnection
theCommand.Parameters.Add("#ItemID", SqlDbType.VarChar).Value = Me.TextBox_ItemID.Text
theCommand.CommandText = "INSERT INTO StockDetail(ItemID, BranchID, Stock) SELECT #ItemID, COUNT(Branch.BranchID), '0' FROM Branch GROUP BY Branch.BranchID"
theDataAdapter.SelectCommand = theCommand
Using theDataAdapter
theCommand.ExecuteNonQuery()
theCommand.Parameters.Clear()
theCommand.Dispose()
theConnection.Close()
SqlConnection.ClearPool(theConnection)
End Using
What do I want now?
Well instead of inserting 1, 1, . . .
I'd like to INSERT it with BR000, BR001 . . . (Based on all existed BranchID)
Here is how you use a parameter in your first insert statement. I think you still have some very serious logic issues here though. This is going to insert 1 row into StockDetail and the values don't make any sense at all. You would be inserting the count of rows from the Branch table as the BranchID which is probably not what you really want. I suspect what you want is a row in this table for each Branch?
theCommand.CommandText = "INSERT INTO StockDetail(ItemID, BranchID, Price) VALUES(
#ItemID,
(SELECT COUNT(BranchID) FROM Branch),
0
)"
theCommand.Parameters.Add("#ItemID", SqlDbType.Varchar).Value = Me.TextBox_ItemID.Text;
I suspect what you really want is something more like this.
theCommand.CommandText = "INSERT INTO StockDetail(ItemID, BranchID, Price)
select #ItemID
, BranchID
, 0
from Branch";
theCommand.Parameter.Add("#ItemID", SqlDbType.Varchar).Value = Me.TextBox_ItemID.Text;
The SQL command text for the insert into StockDetail doesn't do what you say you want to happen. This code, though syntactically incorrect (if you want to use a SELECT as a value, you need to surround it in parentheses like this:
theCommand.CommandText = "INSERT INTO StockDetail VALUES(
'" & Me.TextBox_ItemID.Text & "',
(SELECT COUNT(BranchID) FROM Branch),
'0'
)"
), would insert your ID, a count of the number of branches you have, and a zero into the table.
For what you say you want to have happen, your code would look more like this:
theCommand.CommandText = "INSERT INTO StockDetail SELECT
'" & Me.TextBox_ItemID.Text & "',
BranchID, '0' FROM Branch
)"

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

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

Resources