VB.NET Multiple Selects at once using SQL Server CE - vb.net

I have an array list which contains ids for some items. I would like to perform a multiple select at once from a SQL Server CE database and using my array list which contains what items id to be selected, something similar when doing for example multiple update in oracle (ODP.NET) as explained here: Oracle bulk updates using ODP.NET
where you can pass an array as a parameter.
I would like to do the same but for a multiple select instead in case of SQL Server CE. Is it possible?
DRAFT about what I would like to do:
SqlCeCommand = SqlCeConnection.CreateCommand()
SqlCeCommand.CommandText = "SELECT * FROM MyTable WHERE Id=:ids"
SqlCeCommand.CommandType = CommandType.Text
SqlCeCommand.Parameters.Add(":ids", DbType.Int32, ArrayListOfIds, ParameterDirection.Input)
Using reader As System.Data.SqlServerCe.SqlCeDataReader = SqlCeCommand.ExecuteReader()
Using targetDb As Oracle.DataAccess.Client.OracleBulkCopy = New Oracle.DataAccess.Client.OracleBulkCopy(con.ConnectionString)
targetDb.DestinationTableName = "MyTable"
targetDb.BatchSize = 100
targetDb.NotifyAfter = 100
targetDb.BulkCopyOptions = Oracle.DataAccess.Client.OracleBulkCopyOptions.UseInternalTransaction
AddHandler targetDb.OracleRowsCopied, AddressOf OnOracleRowsCopied targetDb.WriteToServer(reader)
targetDb.Close()
End Using
reader.Close()
End Using

You should try this approach by constructing your "IN" clause and adding each parameter in a for each loop:
SqlCeCommand = SqlCeConnection.CreateCommand()
SqlCeCommand.CommandType = CommandType.Text
Dim sb As New StringBuilder()
Dim i As Integer = 1
For Each id As Integer In ArrayListOfIds
' IN clause
sb.Append("#Id" & i.ToString() & ",")
' parameter
SqlCeCommand.Parameters.Add("#Id" & i.ToString(), DbType.Int32, id, ParameterDirection.Input)
i += 1
Next

If you're calling a Stored Procedure, you can do this:
Serialize the array to a string of XML, like this: https://stackoverflow.com/a/6937351/734914
Call the stored procedure, passing in the string parameter
Parse the string of XML into a local table variable containing the ID's, like this: https://stackoverflow.com/a/8046830/734914
Execute whatever queries you need to using the ID's
The links that I referenced might not be the best examples on the web, but the concept of "serialize to XML, pass string parameter, deserialize XML" should work here

Related

Is there any SQL Statement procedure or code for optional requested field value?

I'm a beginner. I created a database in vb.net and I need to build a query, in the SQL Statement - Table Adapter, which returns records even if parameters are NULL in one or more textbox. To be clear, I have several textboxes (related to fields) with which I can filter record results and I want to refine my research as much as I fill textboxes, reverse if I fill just one of them randomly.
Sorry if I confused you, but I guess you get it anyway.
In its simplest form (assuming SQL server param concepts)
-- Define your columns to pull back/display
select t1.column1, t1.column2, t1.column3...
-- Define the table, give it an alias if you're using more than one or it has a silly name
from thetable t1
-- Apply filters
where
-- For each textbox/column search combo, do this...
(column1 = #field1 or #field1 is null)
or -- If the filter is restrictive, use AND here
(column2 = #field2 or #field2 is null)
or -- If the filter is restrictive, use AND here
...
I would dump the table adapter for this requirement.
I am building the sql string using a StringBuilder. StringBuilder objects are mutable, String is not.
To run this Code
1. I assumed Sql Server. If this is not the case change all the data object (Connectio and Command) to the proper provider.
Add your connection string to the constructor of the connection.
Add your table name where it says "YourTable"
I just used TextBox1 etc. as control names. Use your actual control names
Replace Field1, Field2 etc. with your actual column names.
The parameter names (by convention, they start with #) can be anything you want as long as they match the name you add to the Parameters collection.
You will have to check your database for the actual datatypes of the fields. Be sure to convert the TextBox values to the compatible type. TextBox.Text is a string so it will be compatible to .VarChar but note number types or dates.
I added a Debug.Print to check what the Sql string looks like. Be cautious about where I have spaces when building the string. You can see the result in the immediate window (available from Debug menu).
If you don't already have a DataGridView on your form, add one so you can see the reults of your query.
Finally, always use parameters, use Using...End Using blocks, and open your connection at the last minute.
Private Sub RunDynamicQuery()
Dim sb As New StringBuilder
Dim AndNeeded As Boolean
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand
sb.Append("Select * From YourTable Where ")
If Not String.IsNullOrEmpty(TextBox1.Text) OrElse Not String.IsNullOrWhiteSpace(TextBox1.Text) Then
sb.Append("Field1 = #Field1")
cmd.Parameters.Add("#Field1", SqlDbType.Int).Value = CInt(TextBox1.Text)
AndNeeded = True
End If
If Not String.IsNullOrEmpty(TextBox2.Text) OrElse Not String.IsNullOrWhiteSpace(TextBox2.Text) Then
If AndNeeded Then
sb.Append(" And")
End If
sb.Append(" Field2 = #Field2")
cmd.Parameters.Add("#Field2", SqlDbType.VarChar).Value = TextBox2.Text
AndNeeded = True
End If
If Not String.IsNullOrEmpty(TextBox3.Text) OrElse Not String.IsNullOrWhiteSpace(TextBox3.Text) Then
If AndNeeded Then
sb.Append(" And")
End If
sb.Append(" Field3 = #Field3")
cmd.Parameters.Add("#Field3", SqlDbType.VarChar).Value = TextBox3.Text
AndNeeded = True
End If
sb.Append(";")
cmd.Connection = cn
Debug.Print(sb.ToString)
cmd.CommandText = sb.ToString
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dt
End Sub

String.Format vs Parameter Values SQL Query

I'm trying to figure out if there is a better way to do this
Dim cmd As New SqlCommand
Dim sel As String
Dim obj As New DataHandler
sel = String.Format("SELECT * FROM Customers WHERE Country LIKE '{0}%'", txt_Input.Text)
cmd.CommandText = sel
Me.dgv_Customers.DataSource = obj.SqlDataRetriever(cmd)
Basically what im trying to do is have a textbox that whenever I type a letter, the grid refreshes itself by sending a Query to my SQL server searching for whatever its in the textbox using the LIKE() from SQL. I've been reading about SQL injection and so far everyone suggests to use parameter values (#value) for user input, but if I try to replace the {0} with that it doesn't work. I just wanna make sure that this is a valid way of doing this.
Thanks
Instead just concatenate the string like below. You should consider using parameterized query to avoid SQL Injection.
sel = "SELECT * FROM Customers WHERE Country LIKE '" + txt_Input.Text + "%'";
Use a parameterized query rather. See This Post
Dim cmd as New SqlCommand("SELECT * FROM Customers WHERE Country LIKE #param")
cmd.Parameters.Add("#param", txt_Input.Text +"%")

Display full query in statement with parameters

I have some trouble to debugging my query in vb.net.
I just wanna get full query with value inside it. I use parameters to add value in my query.
This is my code:
'Select query
Dim stm As String = "SELECT *, FORMAT(NOW(),'DD-MM-YYYY HH:NN:SS') as waktu FROM [user] WHERE [username]=? AND [password]=? AND active=TRUE"
Dim cmd As OleDbCommand = New OleDbCommand(stm, db)
'Parameters
Using md5Hash As MD5 = MD5.Create()
Dim pwd As String = GetMd5Hash(md5Hash, Me.tx_password.Text)
cmd.Parameters.Add("p1", OleDbType.VarChar, 25).Value = Me.tx_username.Text
cmd.Parameters.Add("p2", OleDbType.VarChar, 32).Value = pwd
End Using
'Execute Query
MsgBox(stm)
Dim reader As OleDbDataReader = cmd.ExecuteReader(CommandBehavior.SingleRow)
With this code, I just get result like this:
SELECT *, FORMAT(NOW(),'DD-MM-YYYY HH:NN:SS') as waktu FROM [user]
WHERE [username]=? AND [password]=? AND active=TRUE
How to get result like this:
SELECT *, FORMAT(NOW(),'DD-MM-YYYY HH:NN:SS') as waktu FROM [user]
WHERE [username]='adminUser' AND [password]='adminPassword' AND active=TRUE
Parameters are not concatenated into the command, they are sent separately to the database. Otherwise there will be no difference between using a parameterized query and using a concatenated one. (see the answer to a similar question here.)
This means that in order to debug your queries you will have to work a little harder then if your sql was concatenated by the vb.net code.
If your database supports stored procedure I recommend you start using them instead of parameterized queries. You will probably gain performance, and it will be easier to debug.
If not, you can copy the query as is to the sql editor, and use one of the debugger options to get the values of the parameters and copy them one by one to the sql editor.
Place this code below you have added the parameters and you'll have in debugSQL the SQL statement which will be executed
Dim debugSQL As String = cmd.CommandText
For Each param As SqlParameter In cmd.Parameters
debugSQL = debugSQL.Replace(debugSQL.ParameterName, debugSQL.Value.ToString())
Next

Read row by row vb.net

I need to read row by row in a column in a table then I need to store this then call procedure to insert data to a different column using vb.net.
I have already create the DB connection and I know how to call the procedure
but I'm not sure of how to read in the loop and then to assign it to a variable to call it in the store procedure.
Dim drDocs As SqlClient.SqlDataReader
Dim cmdDocs As SqlClient.SqlCommand
Dim Doc As Long
Dim l As Long
Using conn As New SqlConnection(DBpath)
cmdDocs = New SqlClient.SqlCommand("Select (RecordID) from DocID", conn)
drDocs = cmdDocs.ExecuteReader
Do While drDocs.Read
'need it read each row in that field and hold value'
Loop
drDocs.Close()
cmdDocs.Dispose()
If Doc Then
cmdDocs = New SqlClient.SqlCommand("Insert_Doc", conn)
cmdDocs.CommandType = CommandType.StoredProcedure
cmdDocs.Parameters.Add("path", SqlDbType.NVarChar).Value =need to put hold value from reading that cloumn row by row
End If
End If
The code you've provided actually works now. It is as Juergen D says, sql functions like Max(), min() and using Limit will only return 1/certain number of rows based on their conditions.
if I may, just use this SQL command
"select `RecordID` from DocID asc;"
If you want it in descending format, use desc instead
...now reading further, I realize that what you want to do is to store the results, then loop again through it so that you can do an sql command with it, correct? what you can do then is to pass the SQL results to a container (I use datagridviews) then loop through the container.

VB.Net - Efficient way of de-duplicating data

I am dealing with a legacy application which is written in VB.Net 2.0 against a SQL 2000 database.
There is a single table which has ~125,000 rows and 2 pairs of fields with similar data.
i.e. FieldA1, FieldB1, FieldA2, FieldB2
I need to process a combined, distinct list of FieldA, FieldB.
Using SQL I have confirmed that there are ~140,000 distinct rows.
Due to a very restrictive framework in the application I can only retrieve the data as either 2 XML objects, 2 DataTable objects or 2 DataTableReader objects. I am unable to execute custom SQL using the framework.
Due to a very restrictive DB access policy I am unable to add a View or Stored Proc to retrieve as a single list.
What is the most efficient way to combine the 2 XML / DataTable / DataTableReader objects into a single, distinct, IEnumerable object for later processing?
I may have missed something here but could you not combine both DataTables using Merge?
DataTableA.Merge(DataTableB)
You can then use DataTableA.AsEnumerable()
Then see this answer on how to remove duplicates or
You can do this with a DataView as follows: dt.DefaultView.ToTable(True,[Column names])
This is the solution I came up with.
Combine the 2 DataTables using .Merge (thanks to Matt's answer)
Using this as a base I came up with the following code to get distinct rows from the DataTable based on 2 columns:
Private Shared Function GetDistinctRows(sourceTable As DataTable, ParamArray columnNames As String()) As DataTable
Dim dt As New DataTable
Dim sort = String.Empty
For Each columnName As String In columnNames
dt.Columns.Add(columnName, sourceTable.Columns(columnName).DataType)
If sort.Length > 0 Then
sort = sort & ","
End If
sort = sort & columnName
Next
Dim lastValue As DataRow = Nothing
For Each dr As DataRow In sourceTable.Select("", sort)
Dim add As Boolean = False
If IsNothing(lastValue) Then
add = True
Else
For Each columnName As String In columnNames
If Not (lastValue(columnName).Equals(dr(columnName))) Then
add = True
Exit For
End If
Next
End If
If add Then
lastValue = dr
dt.ImportRow(dr)
End If
Next
Return dt
End Function