Use SQL Query in VB.net to retireve adjacant row data - sql

I am currently coding in VB.net using windows form applications and an sql server for my tables. I am creating an order form with two comboboxes, one for the type of material to be ordered and one for a name. There is also a submit button at the bottom to run the SQL "Insert Into" code. The material combobox is filled with a column of material types from an SQL table called "tbl.channel". Each material type under that column has a part number, ID, and bundle size associated with that row. I want ALL of the information associated with that material type to write into a new table that records all the orders, with the user only selecting the material type from a combobox. How can I use a "Select From" sql code to pull the associated information with that material type to be written into a new table that tracks all the material ordered?
Try
Dim connectionstring As String = Nothing
Dim connection As SqlConnection
Dim command As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataTable
Dim i As Integer = 0
Dim sql As String = Nothing
connectionstring = "DATA SOURCE = BNSigma\Core ; integrated security = true"
sql = "Select Channel, [Bundle Size], ID from Production.dbo.tblchannel"
connection = New SqlConnection(connstring)
connection.Open()
command = New SqlCommand(sql, connection)
adapter.SelectCommand = command
adapter.Fill(ds)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Try
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As SqlCommand = New SqlCommand("INSERT INTO Production.dbo.tbl (Channel, OrderedBy, Date1, BundleSize, ID) Values (#Channel, #Orderedby, #getdate(), #BundleSize, #ID)", conn1)
With comm1.Parameters
.AddWithValue("#Channel", CBChannel.SelectedValue)
.AddWithValue("#OrderedBy", CBName.SelectedValue)
.AddWithValue("#BundleSize", CBChannel.SelectedValue)
.AddWithValue("#ID", CBChannel.SelectedValue)
End With
End Using
End Using
Catch ex As Exception
MsgBox("Unable to make SQL connection")
MsgBox(ex.ToString)
End Try

I'm not certain I understand your goal, but are you looking to just do this?
INSERT Production.dbo.tbl (Channel, OrderedBy, Date1, BundleSize, ID)
SELECT Channel, #Orderedby, getdate(), BundleSize, ID
FROM tbl.channel
WHERE ID = #ID
I am pretty well convinced though that you should only be writing the channel.ID to the orders table -- do you have a compelling reason to write the extra values?

SQL lets you use a SELECT query to populate the values for an INSERT statement. Something like this:
Public Sub PopulateOrder(ByVal MaterialID As Integer, ByVal SalesName As String)
Dim sql As String = "INSERT INTO Production.dbo.tbl (Channel, OrderedBy, Date1, BundleSize, ID) SELECT Channel, #SalesName, current_timestamp, [Bundle Size], ID from Production.dbo.tblchannel WHERE ID = #MaterialID"
Using cn As New SqlConnection("connection string here"), _
cmd As New SqlCommand(sql, cn)
'Better to declare a specific database type than let .AddWithValue() try to infer one for you
cmd.Parameters.Add("#SalesName", SqlDbType.NVarChar, 50).Value = SalesName
cmd.Parameters.Add("#MaterialID", SqlDbtype.Int).Value = MaterialID
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Call it like with code similar to this:
PopulateOrder(CBChannel.SelectedValue, CBName.SelectedValue)
But for what it's worth, it's almost always a bad idea to duplicate this information across tables.

Related

Hi folks. I am trying to update an app to VB dot net from vb6 and have enouctered a really basic problem. I will add the code of course in a sec. I

Trying to update an old VB6 app to VB.Net. I am having trouble with syntax, I think. In any case it is a simple matter of inserting a new record to the autolog table. (code below).
I would like to ask something else that is often not documented too. It seems that I have to use command builders and so on - is there no way I can simply use an SQL statement and execute it against the background table? The tables are in Access while I am developing but will be scaled up on the final release of the software.
I have altered my code to the following by making use of the error suggestions at the foot of mygui.
It now looks like this and the only thing is that it is throwing a logic error at me which is that every end function must have a preceding "function". Perhaps I am being a little bit dim
Function MAutolog(ByVal Action As String) As Boolean
Dim SQL = "Insert Into Autolog (Action) Values (#Action)"
Using con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb"),
cmd As New OleDb.OleDbCommand(SQL, con)
cmd.Parameters.Add("#Action", OleDb.OleDbType.VarChar).Value = Action
con.Open()
cmd.ExecuteNonQuery()
End Using
MAutolog = True
End Function
I would like to thank you for your help in advance. I can not tell you how much I will appreciate it.
Code
Module ModFunctions
Function MAutolog(ByVal UserID As Long, ByVal Action As String) As Boolean
Dim dbprovider As String
Dim dbsource As String
Dim mydocumentsfolder As String
Dim fulldatabasepath As String
Dim TheDatabase As String
Dim SQL As String
Dim DS As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb")
con.Open()
'----------------------------
SQL = "Select * from Autolog"
da = New OleDb.OleDbDataAdapter(SQL, con)
da.Fill(DS, "Log")
con.Close()
Dim CB As New OleDb.OleDbCommandBuilder(da)
Dim DSNEWROW As DataRow
DSNEWROW = DS.Tables("Log").NewRow()
DSNEWROW.Item("UserID") = UserID
DSNEWROW.Item("Action") = Action
DS.Tables("log").Rows.Add(DSNEWROW)
da.Update(DS, "log")
MAutolog = True
End function
Database objects like Connection and Command use unmanaged code and need their Dispose methods to release these resources. Either call this method on these objects or use Using...End Using blocks which will do this for you even if there is an error. In this code, both the Connection and Command are included in the Using block by separating them be a comma.
By Val is the default so is not necessary.
Always use parameters to avoid sql injection. Using values directly from user input can allow malicious code to be executed on your database. The value of a parameter is not considered as executable code by the database.
OleDb does not care about parameter names. You could just as easily use ? in the sql statement. I use names for readability. You do need some sort of name to add the parameter. OleDb considers the position of the parameter in the sql statement. The position must match the order that the parameters are added to the parameters collection.
This is the code for the Insert if UserID in an auto-number field. You do not provide a value for auto-number fields. The database will handle that.
Function MAutolog(Action As String) As Boolean
Dim SQL = "Insert Into Autolog (Action) Values (#Action)"
Using con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb"),
cmd As New OleDbCommand(SQL, con)
cmd.Parameters.Add("#Action", OleDbType.VarChar).Value = Action
con.Open()
cmd.ExecuteNonQuery()
End Using
MAutolog = True
End Function
If UserID is not auto-number
Function MAutolog(UserID As Long, Action As String) As Boolean
Dim SQL = "Insert Into Autolog (UserID, Action) Values (#UserID, #Action)"
Using con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb"),
cmd As New OleDbCommand(SQL, con)
cmd.Parameters.Add("#UserID", OleDbType.Integer).Value = UserID
cmd.Parameters.Add("#Action", OleDbType.VarChar).Value = Action
con.Open()
cmd.ExecuteNonQuery()
End Using
MAutolog = True
End Function

Visual basic (.net) Insert new record question

i am a novice, trying to add a new record to a php myadmin database, the secondDB requires an "Id" to be inserted with the data.
the rest of the project uses data bound fileds.
so i generate the new record with
FirstDB.addnew()
secondDB.addnew()
then try to run the below
Call Connection() 'this gets My.Settings.companyConnectionString and opens the connection
Dim str As String = ("SELECT max(Id) FROM FirstDB")
cmd = New MySqlCommand(str, conn)
cmd.CommandType = CommandType.Text
Dim result As Integer = cmd.ExecuteScalar +1 'this will get the number and increase by one
Using cmd As New MySqlCommand()
With cmd
.CommandText = "insert into SecondDB(`id`) values (#id)"
.Parameters.AddWithValue("#id", result)
End With
End Using
conn.Dispose()
also tryed
DataSet.Secondtable.Id.DefaulValue = result
SecondDBbindingSource.Current.item("Id") = result
the secondBD refuses to save without the missing "ID".
if you put the resut in a data bound box it works out fine, but i dont want to have text boxes scatterd around.
can anyone give me some guideance ?
FirstDB.addnew()
secondDB.addnew()
I have no idea what this code is doing.
Call Connection()
Don't do this. Connections need to be declared and disposed in the method where they are used. Using blocks take care of this for us even it there is an error.
Dim str As String = ("SELECT max(Id) FROM FirstDB")
This is not a good way to find the Id you are looking for. In MySql you can add SELECT LAST_INSERT_ID(); to the Insert for FirstDB (terrible name for a table). In a multi-user environment Max will fail.
cmd.CommandType = CommandType.Text
The default type for a command is the Text type so you don't have to explicitly set this property. Interesting that you don't set this property when you create a new command a few lines down.
Dim result As Integer = cmd.ExecuteScalar + 1
ExecuteScalar returns an Object. You cannot add one to an Object. Why do you want to increment this value? The foreign key in secondDB should match the primary key in FirstDB. You said in comments both tables have a primary key field that is auto increment.
.CommandText = "insert into SecondDB(`id`) values (#id)"
Is that all you are entering into the new record? Not a very informative record.
conn.Dispose()
What if an error occurred. Your connection would never be closed or disposed.
DataSet.Secondtable.Id.DefaulValue = result
SecondDBbindingSource.Current.item("Id") = result
I have no idea what you are doing here.
I have to make up a table structure for the 2 tables (not DB, tables).
Private Sub OPCode(Company As String, Contact As String, Address As String)
Dim IdFromFirstDB As Integer
Dim sql = "Insert Into FirstDB (CompanyName, ContactName) Values (#Name, #Contact) Select LAST_INSERT_ID();"
Using cn As New MySqlConnection(My.Settings.companyConnectionString)
Using cmd As New MySqlCommand(sql, cn)
cmd.Parameters.Add("#Name", MySqlDbType.VarChar, 200).Value = Company
cmd.Parameters.Add("#Contact", MySqlDbType.VarChar, 100).Value = Contact
cn.Open()
IdFromFirstDB = CInt(cmd.ExecuteScalar)
End Using
sql = "Insert Into secondDb (Address, CompanyID) Values (#Address, #ID);"
Using cmd As New MySqlCommand(sql, cn)
cmd.Parameters.Add("#Address", MySqlDbType.VarChar, 200).Value = Address
cmd.Parameters.Add("#ID", MySqlDbType.Int32).Value = IdFromFirstDB
cmd.ExecuteNonQuery()
End Using
End Using
End Sub

How to populate a combobox from two different SQL Server database tables

I am trying to create a system that will load items from a database. There are two comboboxes; combobox1 which loads items from database table 1 and combox2 which loads items from database table 2.
Both tables are in the same database.
Here is was I tried but when I run the system I get this error:
(Conversion from string "SELECT * FROM dbo.Dishes" to type 'Long' is not valid.)
Here is the code I'm using:
Dim connection As New SqlConnection("Server = DESKTOP-1373H91; Initial Catalog = MealPreOrderSystem; Integrated Security = True")
connection.Open()
Dim query As String = "SELECT * FROM dbo.Dishes" And "SELECT * FROM dbo.Desserts"
Dim cmd As SqlCommand
cmd = New SqlCommand(query, connection)
Dim reader As SqlDataReader
reader = cmd.ExecuteReader
While reader.Read
cbxType.Items.Add(reader.Item("MealName"))
cbxType.Items.Add(reader.Item("DessertName"))
End While
connection.Close()
In VB.NET,AND is an operator.It is used to perform conjunction between either Booleans or Integers/Doubles/any numeric expression.Lets take your query string as an example :
Dim query As String = "SELECT * FROM dbo.Dishes" And "SELECT * FROM dbo.Desserts"
You are using AND here to join 2 sentences/strings which wouldn't result in anything rather it is trying to cast it as a Long.
Try to execute this command in SQL and you won't find any luck :(.
Your statements are correct :
SELECT * FROM dbo.Dishes
SELECT * FROM dbo.Desserts
But the way you are trying to achieve your goals is incorrect :(.
To get the data from the database into your combobox, what you can do is either use two comboboxes with separated SQL Queries/SQL Commands or you can use one combobox where you add data from both the databases but separate them with some special characters such as a comma ,
A sample may look like :
With one combobox
Dim cmd1 as new SqlCommand("SELECT * FROM dbo.Dishes",connection)
Dim dr as SqlDatareader = cmd1.ExecuteReader
While dr.Read
mycombo1.Items.Add(dr(0)) ' Here 0 is the column count,change it as required
End while
Dim cmd2 as new SqlCommand("SELECT * FROM dbo.Desserts",connection)
Dim dr2 as SqlDatareader = cmd2.ExecuteReader
While dr2.Read
mycombo2.Items.Add(dr2(0)) ' Here 0 is the column count,change it as required
End while
With 1 combobox
Here it gets a bit complicated.Firstly you need to populate your combobox from the data received from the first dataReader.Then, when the 2nd datareader is reading the data , you need to update the existing data/Item of the combobox keeping the existing data/item but adding new data/item to each existing data/item(separating them with ,).
Sample :
Dim i as Integer
Dim cmd1 as new SqlCommand("SELECT * FROM dbo.Dishes",connection)
Dim dr as SqlDatareader = cmd1.ExecuteReader
While dr.Read
mycombo1.Items.Add(dr(0))
End while
Dim cmd2 as new SqlCommand("SELECT * FROM dbo.Desserts",connection)
Dim dr2 as SqlDatareader = cmd2.ExecuteReader
While dr2.Read
mycombo1.Items(i) = myconbo1.Items(i) & "," & dr2(0)
i = i + 1
End while
Now, NOTE THAT I AM USING MULTIPLE DATAREADERS WITH THE SAME CONNECTION ,SO YOU MAY NEED TO INCLUDE MultipleActiveResultSets=True IN YOUR CONNECTION STRING or ENCLOSE THE DATAREADERS IN USING STATEMENTS or CALL dataReader.Close AFTER EACH DATAREADER HAS COMPLETED READING FROM THE DATABASE
This will solve your issue :)
Looks like you don't know how to write SQL queries (and your VB syntax itself looks faulty - string AND string?).
Dim connection As New SqlConnection("Server = DESKTOP-1373H91; Initial Catalog = MealPreOrderSystem; Integrated Security = True")
Dim query As String = <cmdString>
SELECT MealName as Name FROM dbo.Dishes
union
SELECT DessertName as Name FROM dbo.Desserts
</cmdString>
Dim cmd As SqlCommand
Dim reader As SqlDataReader
connection.Open()
cmd = New SqlCommand(query, connection)
reader = cmd.ExecuteReader
While reader.Read
cbxType.Items.Add(reader.Item("Name"))
End While
connection.Close()
Note: You are saying 2 comboboxes but your code seemed to be loading all the items to a single combobox. If you really need 2 comboboxes then use 2 SqlCommand and Reader loops (actually it would be better if you simply have used Linq for this).
You should be a bit more specific on what columns you are pulling from the 2 tables. if they are similar, you could write a sql query to UNION ALL the fields with a simple control to identify which record came from which table.
Example of SQL command string:
"SELECT 'M' AS Ctl, MealName AS aName FROM dbo.Dishes " &
"UNION ALL " &
"SELECT 'D' AS Ctl, DessertName AS aName FROM dbo.Desserts"
As mentioned by many here already, it seems like you are referencing only 1 ControlBox to list the fields returned cbxType
below is the reader (adapted to 2 ComboBoxes):
While reader.Read
Select Case reader.Item("Ctl")
Case "M"
cbxMType.Items.Add(reader.Item("aName"))
Case "D"
cbxDType.Items.Add(reader.Item("aName"))
End Select
End While
Hope this helps

Visual Basic, Copying Success but does not Insert data into SQL TABLE

I have some problems here. I need help.
Recently, I have created a local database called stock.mdf and the application will be getting all the data from the hosting MySQL database into this local SQL Server database.
I am using sqlBulkCopy to inserting all the data. I have tried to view it after inserting. But when I close my application, I head back to check the table data. It does not inserted. Why is that?
Here is my code:
Here will be retrieving the data from the hosting
Dim connStr As String = "server=xxxx;user=xxx;database=xxx;password=xxxx;"
Dim conn As New MySqlConnection(connStr)
Dim cmd As New MySqlCommand
Dim Adapter As New MySqlDataAdapter
Dim StockData As New DataTable
Try
Dim SQL As String = "SELECT * FROM stock"
Console.WriteLine("Connecting to MYSQL.....")
conn.Open()
cmd.Connection = conn
cmd.CommandText = SQL
Adapter.SelectCommand = cmd
Adapter.Fill(StockData)
' StockViewGrid.DataSource = StockData
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
conn.Close()
Console.Write("Done")
End Try
This will be the places where sqlBulkCopy working:
As well, I am trying to view from the stock table.
Dim Local_connectionStr As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|stock.mdf;Integrated Security=True"
Dim Local_conn As New SqlConnection(Local_connectionStr)
Dim Local_cmd As New SqlCommand
Dim Local_Adapter As New SqlDataAdapter
Dim Local_StockData As New DataTable
Try
Using sqlBulkCopy As New SqlBulkCopy(Local_conn)
'Set the database table name
sqlBulkCopy.DestinationTableName = "stock"
'[OPTIONAL]: Map the DataTable columns with that of the database table
sqlBulkCopy.ColumnMappings.Add("stockId", "stockId")
sqlBulkCopy.ColumnMappings.Add("id_android", "id_android")
sqlBulkCopy.ColumnMappings.Add("itemCode", "itemCode")
sqlBulkCopy.ColumnMappings.Add("quantity", "quantity")
Local_conn.Open()
sqlBulkCopy.WriteToServer(StockData)
Local_conn.Close()
End Using
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
Local_conn.Close()
Console.Write("Done")
End Try
Try
Dim SQL As String = "SELECT * FROM stock"
Console.WriteLine("Connecting to MYSQL.....")
Local_conn.Open()
Local_cmd.Connection = Local_conn
Local_cmd.CommandText = SQL
Local_Adapter.SelectCommand = Local_cmd
Local_Adapter.Fill(Local_StockData)
StockViewGrid.DataSource = Local_StockData
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
Local_conn.Close()
Console.Write("Done")
End Try
Since I can't comment (not enough points) I will put my thoughts here. Can you check that you got the expected data with a
Console.WriteLine(StockData.Rows.Count.ToString)
Console.ReadLine()
Also, your destination table doesn't have a PK that is auto increment, does it?
Sorry about the comment as an answer. (Untested code)
Unfortunately your code extracts are lacking headers etc, so are not complete, and I cannot be absolutely certain, BUT in your retrieving routine you seem to be declaring StockData as a local variable. This means that, although this may well be being filled with the data from MySQL, it is immediately discarded on exiting from this routine. Therefore the StockData variable in the sqlBulkCopy routine will be empty, and therefore will insert nothing. You need to fix your scope and make sure that the StockData read from MySQL is the same StockData used in SqlBulkCopy.

How can I read a specific column in a database?

I hava a Table named DTR_Table it has 8 columns in it namely:
EmployeeID,Date,MorningTime-In,MorningTime-Out,AfternoonTime-In,AfternoonTime-Out,UnderTime,Time-Rendered.I want to read the column "AfternoonTime-In".
Following is my code. It reads my "AfternoonTime-In" field, but it keeps on displaying "Has Rows" even if there is nothing in that column.
How can I fix this?
Connect = New SqlConnection(ConnectionString)
Connect.Open()
Dim Query1 As String = "Select [AfternoonTime-Out] From Table_DTR Where Date = #Date and EmployeeID = #EmpID "
Dim cmd1 As SqlCommand = New SqlCommand(Query1, Connect)
cmd1.Parameters.AddWithValue("#Date", DTRform.datetoday.Text)
cmd1.Parameters.AddWithValue("#EmpID", DTRform.DTRempID.Text)
Using Reader As SqlDataReader = cmd1.ExecuteReader()
If Reader.HasRows Then
MsgBox("Has rows")
Reader.Close()
Else
MsgBox("empty")
End If
End Using`
After returning the DataReader you need to start reading from it if you want to extract values from your query.
Dim dt = Convert.ToDateTime(DTRform.datetoday.Text)
Dim id = Convert.ToInt32(DTRform.DTRempID.Text)
Using Connect = New SqlConnection(ConnectionString)
Connect.Open()
Dim Query1 As String = "Select [AfternoonTime-Out] From Table_DTR
Where Date = #Date and EmployeeID = #EmpID"
Dim cmd1 As SqlCommand = New SqlCommand(Query1, Connect)
cmd1.Parameters.Add("#Date", SqlDbType.DateTime).Value = dt
cmd1.Parameters.Add("#EmpID", SqlDbType.Int).Value = id
Using Reader As SqlDataReader = cmd1.ExecuteReader()
While Reader.Read()
MessageBox.Show(Reader("AfternoonTime-Out").ToString())
Loop
End Using
End Using
Note that I have changed the AddWithValue with a more precise Add specifying the parameter type. Otherwise, your code will be in the hand of whatever conversion rules the database engine decides to use to transform the string passed to AddWithValue to a DateTime.
It is quite common for this conversion to produce invalid values especially with dates