I have an Arraylist of Dates as such
8/30/2020
8/27/2020
9/28/2020
9/9/2020
8/31/2020
8/29/2020
I then have a query with an in clause for the dates as such
allQuery = "Select pj.ProjectName, tcd.Date, sum(tcd.Executed), sum(tcd.Passed), sum(tcd.Passedbug), sum(tcd.Flaky), sum(tcd.Failed), sum(tcd.Newfailures) "
allQuery &= "From qastats.dbo.TestCaseDetails tcd inner Join qastats.dbo.Pipelines p on tcd.PipelineID=p.PipelineID inner Join qastats.dbo.Projects pj on p.ProjectID=pj.ProjectID "
allQuery &= "where pj.ProjectName =#projectname "
allQuery &= "And tcd.Date in (#dates) group by pj.ProjectName, tcd.Date"
I want to take the list of dates in the Array list and put it in this format (same as String.Join)
8/30/2020,8/27/2020,9/28/2020,9/9/2020,8/31/2020,8/29/2020
so I can pass them in as a value for the parameter
comm.Parameters.Add("#dates", SqlDbType.DateTime).Value = ListofDates
Is there a way to do it the way I want or a better way?
Thanks
As suggested on the comments, use List instead of ArrayList.
Use a table valued parameter for the dates.
You'll need to create the table type in the database like this (I modified your query slightly moving the dates validation into a join if you want it in the where you can uncomment the commented line and comment the one for the join to #dates):
CREATE TYPE dbo.DatetimeTvp AS TABLE
(
value DATETIME NOT NULL
)
And then you can use this code:
Private Sub RunQuery()
Dim dates As IList(Of DateTime) = New List(Of DateTime)({DateTime.Now, DateTime.UtcNow})
Dim sb As StringBuilder = New StringBuilder()
sb.AppendLine(" Select pj.ProjectName, tcd.Date, sum(tcd.Executed), sum(tcd.Passed), sum(tcd.Passedbug), sum(tcd.Flaky), sum(tcd.Failed), sum(tcd.Newfailures) ")
sb.AppendLine(" From qastats.dbo.TestCaseDetails tcd ")
sb.AppendLine(" inner Join qastats.dbo.Pipelines p on tcd.PipelineID=p.PipelineID ")
sb.AppendLine(" inner Join qastats.dbo.Projects pj on p.ProjectID=pj.ProjectID ")
sb.AppendLine(" inner Join #dates dts on dts.value = tcd.Date ")
sb.AppendLine(" where pj.ProjectName =#projectname ")
'sb.AppendLine(" and tcd.Date in (select value from #dates) ")
sb.AppendLine(" group by pj.ProjectName, tcd.Date ")
Using cn As SqlConnection = New SqlConnection(ConnectionString)
Using cmd As SqlCommand = New SqlCommand(sb.ToString(), cn)
Dim pDates = GetTvp("#dates", dates.Distinct())
cmd.Parameters.Add(pDates)
Dim ds As DataSet = New DataSet()
Dim sqlAd = New SqlDataAdapter(cmd)
sqlAd.Fill(ds)
Print(ds)
End Using
End Using
End Sub
Private Function GetTvp(ByVal name As String, ByVal dates As IEnumerable(Of DateTime)) As SqlParameter
Dim dt As DataTable = New DataTable()
dt.Columns.Add("value", GetType(DateTime))
For Each d In dates
dt.Rows.Add(d)
Next
Dim p As SqlParameter = New SqlParameter(name, dt)
p.SqlDbType = SqlDbType.Structured
p.TypeName = "dbo.DatetimeTvp"
Return p
End Function
Related
How to concatenate
ORDER BY
clause in VB.NET?
Here's what I've tried:
Using command As New SqlCommand()
command.Connection = conn
Dim parameterNames As New List(Of String)(dt_data.RowCount - 2)
For i As Integer = 0 To dt_data.RowCount - 3
Dim parameterName As String = "#meter_num_" & i
Dim meter_number As String = dt_data.Rows(i).Cells(3).Value
command.Parameters.AddWithValue(parameterName, meter_number)
parameterNames.Add(parameterName)
Next
command.CommandText = String.Format("SELECT * FROM customer WHERE cycle = #cycle and meter_num IN ({0})", String.Join(",", parameterNames), ("ORDER BY Client_Name ASC"))
command.Parameters.AddWithValue("#cycle", cycle2last)
Dim da As New SqlDataAdapter(command)
Dim ds As New DataSet
da.Fill(ds, "customer")
Compare_Reading.dt_last2month.DataSource = ds.Tables(0)
End Using
I wanted it to be like this
Select * from table_name
where column_name = #column and column2 = #column2
ORDER BY column_name ASC
To do that in a single instruction you need to replace
Compare_Reading.dt_last2month.DataSource = ds.Tables(0)
With:
Compare_Reading.dt_last2month.DataSource = (From existing As DataRow In ds.Tables(0).Select Order By existing.Item("your_filed_name_to_order_here") Ascending).CopyToDataTable
One of the nice things about List(Of T) is that you don't need to know the size before adding items. It will expand as necessary. So, I deleted the int32 from the constructor.
I think you want dt_data.RowCount -2 in For loop or you will skip the last row. I changed your .AddWithValue to .Add. You will have to check your database for the correct datatypes (I guessed) and adjust the code accordingly.
I think your main problem was in String.Format. You added the 2 parameters but neglected to put in the {1}.
I added a Debug.Print so you can check that your Select looks like you expect. This will appear in the immediate window when you run in debug. It won't effect the release version.
You don't need a DataAdapter or DataSet just a DataTable. Assign the .DataSource outside of the Using block.
I don't think there is any concern about sql injection because you have properly used parameters for all the variables.
Private Sub OPCode(cycle2last As String)
Dim dt As New DataTable
Using conn As New SqlConnection("Your connection string")
Using command As New SqlCommand()
command.Connection = conn
Dim parameterNames As New List(Of String)
For i As Integer = 0 To DataGridView1.RowCount - 2
Dim parameterName As String = "#meter_num_" & i
Dim meter_number As String = DataGridView1.Rows(i).Cells(3).Value.ToString
command.Parameters.Add(parameterName, SqlDbType.VarChar).Value = meter_number
parameterNames.Add(parameterName)
Next
command.CommandText = String.Format("SELECT * FROM customer WHERE cycle = #cycle and meter_num IN ({0}) {1}", String.Join(",", parameterNames), ("ORDER BY Client_Name ASC;"))
command.Parameters.Add("#cycle", SqlDbType.VarChar).Value = cycle2last
Debug.Print(command.CommandText)
conn.Open()
dt.Load(command.ExecuteReader)
End Using
End Using
DataGridView2.DataSource = dt
End Sub
i type a query for my filter, the query needs to join 2 or 3 tables in order for me to do my filter. when i try to use inner join i got a inner join not supported error. the database i use is ms.access. I'll provide the table contents in the comments.
i tried this code it works but the assignment require inner join
strSQL = "SELECT m.primaryTitle, m.startYear as startYear, m.genres as genres, r.averageRating as Rating FROM basic m, Rating r where m.tconst=r.tconst AND (" & fieldselect & " LIKE '%" & TextBox1.Text & "%')"
Select Case ComboBox1.Text
Case "year"
fieldselect = "startYear"
Case "genre"
fieldselect = "genres"
Case "rating"
fieldselect = "averageRating"
End Select
conn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Movies.accdb; Persist Security Info=False;")
strSQL = "SELECT m.primaryTitle, m.startYear as startYear, m.genres as genres, r.averageRating as Rating FROM basic m INNER join Rating r on m.tconst=r.tconst (" & fieldselect & " LIKE '%" & TextBox1.Text & "%')"
conn.Open()
da = New OleDbDataAdapter(strSQL, conn)
Dim ds As New DataSet("Movies")
da.Fill(ds, "Movies")
DataGridView1.DataSource = ds.Tables("Movies")
conn.Close()
strSQL = "SELECT m.primaryTitle, m.startYear as startYear, m.genres as genres, r.averageRating as Rating FROM basic m, Rating r where m.tconst=r.tconst AND (" & fieldselect & " LIKE '%" & TextBox1.Text & "%')"
the result of this code is not what i expected, when i selected one of the items from the combobox to filter, i got everything display in the datagrid view, but i want to show specific columns or few columns of one table.
Try this one:
Dim da as oledbdataadapter = new oledbdataadapter ("Select column_name from table A inner join table B on A.column_name = B.column_name WHERE column_name = '" & combobox.text & "'",oledbconnection)
dim dt as datatable = new datatable
da.fill(dt)
datagridview.datasource = dt
I write a sql statement into vb.net to fetch data from msaccess where date equal to patepicker control. But here syntax error.
My code given below:-
Dim ct As String = "select * from add_student where _Date <= #" & dtDate1.ToString("MM/dd/yyyy") & "#"
cmd = New OleDbCommand(ct)
cmd.Connection = con
rdr = cmd.ExecuteReader()
Note:- _Date column had Date/Time Data type in ms access database
Please suggest me, Where is mistake
You should always use parameters:
dim sqlQuery ="Select * from add_student where _Date = ?"
using conn = New OleDbConnection("connectionstring")
conn.open()
Using selectCmd As New OleDbCommand(sqlQuery, conn)
selectCmd.Parameters.Add("_Date", OleDbType.Date).Value = dtDate1
using rdr = selectCmd.ExecuteReader()
while rdr.read()
End While
End Using
End Using
End Using
Your issue may be that "/" is not a slash but the localized date separator.
Thus, force slashes:
Dim ct As String = "select * from add_student where _Date <= #" & dtDate1.ToString("MM'/'dd'/'yyyy") & "#"
and perhaps brackets for the weird field name:
Dim ct As String = "select * from add_student where [_Date] <= #" & dtDate1.ToString("MM'/'dd'/'yyyy") & "#"
I have a SQL Server stored procedure (dbo.WiegenMain) as below:
ALTER PROCEDURE [dbo].[WiegenMain]
AS
BEGIN
insert into dbo.wiegen (Tag, Aufträge_anzahl, Wiegeraum)
select
dbo.datepart2(BUCHUNG_BIS) as Tag,
count(distinct AUFTRAGSNUMMER), Kurztext as Wiegeraum
from
dbo.tblZEITERFASSUNG
inner join
dbo.tblBELEGUNGSEINHEIT on tblZEITERFASSUNG.ID_BELEGUNGSEINHEIT = tblBELEGUNGSEINHEIT.ID
where
ID_BUCHUNGSART = 9
and ID_BELEGUNGSEINHEIT IN
(SELECT ID_BELEGUNGSEINHEIT
FROM dbo.tblPROZESS_BELEGUNGSEINHEIT
WHERE ID_PROZESS = 3)
and ABSCHLUSS = 1
AND dbo.DatePart2(BUCHUNG_BIS) = dbo.DatePart2(getdate())
group by
dbo.DatePart2(BUCHUNG_BIS), Kurztext
END
I want to call this stored procedure in Microsoft Access using VBA, I have tried the following :
First try:
Function InsertWiegen()
Dim conn As ADODB.Connection
Dim rcs As ADODB.Recordset
Dim strSQL As String
Dim strDel As String
Set conn = CurrentProject.Connection
strDel = "DELETE dbo.wiegen WHERE Tag = '" & Date & "'"
strSQL = "INSERT INTO dbo.wiegen ([Tag], [Aufträge_anzahl], [Wiegeraum]) " & _
"SELECT dbo.DatePart2([BUCHUNG_BIS]) as [Tag], count(distinct [AUFTRAGSNUMMER]) as [Aufträge_anzahl], Kurztext as [Wiegeraum] from dbo.tblZEITERFASSUNG inner join dbo.tblBELEGUNGSEINHEIT on tblZEITERFASSUNG.ID_BELEGUNGSEINHEIT=tblBELEGUNGSEINHEIT.ID where ID_BUCHUNGSART=9 and ID_BELEGUNGSEINHEIT in (SELECT ID_BELEGUNGSEINHEIT FROM dbo.tblPROZESS_BELEGUNGSEINHEIT WHERE ID_PROZESS = 3) and [ABSCHLUSS]=1 AND dbo.DatePart2([BUCHUNG_BIS])= dbo.DatePart2('" & Date & "') group by dbo.DatePart2([BUCHUNG_BIS]), [Kurztext]"
Set rcs = conn.Execute(strDel)
conn.Execute (strSQL)
Set rcs = Nothing
conn.Close
Exit Function
End Function
Second Try:
Function InsertWiegen()
Dim conn As ADODB.Connection
Dim rcs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim strSQL As String
Dim strDel As String
Set conn = CurrentProject.Connection
'Set cmd.ActiveConnection = CurrentProject.Connection
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandText = "WiegenMain"
cmd.CommandType = adCmdStoredProc
strDel = "DELETE dbo.wiegen WHERE Tag = '" & Date & "'"
Set rcs = conn.Execute(strDel)
cmd.Execute
Set rcs = Nothing
Set cmd = Nothing
conn.Close
Exit Function
End Function
dbo.datepart2() Function:
ALTER function [dbo].[DatePart2] (#date datetime)
returns datetime
as
begin
return(cast(CONVERT(varchar(12), #date, 101) AS datetime))
end
Problem: Both the methods give the error -
'The conversion of a char datatype to a datetime datatype resulted in
an out-of-range datetime value.'
The stored procedure is working perfectly in SQL Server Management Studio, but raises error in Microsoft Access. The strDel is working fine, it deletes the records from the database table sucessfully, problem is with the strSQL query. I would really appreciate, if anyone can find out what is causing the problem..
The text that you are inserting into your SQL statement for the Date will depend on your international settings. Try converting it to 'YYYY-MM-DD' like this:-
strDel = "DELETE dbo.wiegen WHERE Tag = '" & format (Date, "YYYY-MM-DD") & "'"
What data type is Tag in SQL?
If it is numeric then
strDel = "DELETE dbo.wiegen WHERE Tag = " & format (Date, "DD")
Solved the problem in another way:
strSQL = "INSERT INTO dbo.wiegen ([Tag], [Aufträge_anzahl], [Wiegeraum])
SELECT left([BUCHUNG_BIS],11) as [Tag], count(distinct [AUFTRAGSNUMMER]) as [Aufträge_anzahl], Kurztext as [Wiegeraum]
from dbo.tblZEITERFASSUNG
inner join
dbo.tblBELEGUNGSEINHEIT on tblZEITERFASSUNG.ID_BELEGUNGSEINHEIT=tblBELEGUNGSEINHEIT.ID
where ID_BUCHUNGSART=9 and ID_BELEGUNGSEINHEIT
in
(SELECT ID_BELEGUNGSEINHEIT FROM dbo.tblPROZESS_BELEGUNGSEINHEIT WHERE ID_PROZESS = 3)
and [ABSCHLUSS]=1 AND left([BUCHUNG_BIS],11)= left(GETDATE(), 11)
group by left([BUCHUNG_BIS],11), [Kurztext]"
Replaced my datepart2 function with left() function, now it executes successfully without any error.
I want to update TableA with values from TableB on a nightly basis. Right now, I'm trying to do this with SSIS 2005 using a Script Task with the SQL in it. Each time I try to do the update in this manner, I get a time-out error.
Is there a better way to do this in SSIS?
Current information below:
Public Sub Main()
Const Component_Name As String = "Updating TableA Data"
Const Conn_String As String = "Data Source=DB_A;Initial Catalog=TableA;Integrated Security=SSPI;"
Const sql_Emp As String = "Update TableA Set Contract = c.License_No, SEIN = convert(varchar, c.Lic_Exp_Date, 101) " _
& "From Server.DB_B.dbo.TableB c Inner Join TableA b on " _
& "rtrim(ltrim(c.business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14)))) " _
& "Where c.Lic_Exp_Date = (select Max(Lic_Exp_Date) From Server.DB_B.dbo.TableB " _
& "Where rtrim(ltrim(business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))) " _
& "and convert(varchar, c.Lic_Exp_Date, 101) <> convert(varchar, b.SEIN, 101)"
Dim con As SqlConnection = New SqlConnection(Conn_String)
Try
Dts.Log("Opening DB Connection: " & con.ConnectionString, 0, Nothing)
con.Open()
Dim duh As New SqlCommand(sql_Emp, con)
duh.ExecuteNonQuery()
con.Close()
Dts.Log(String.Format(Component_Name), 0, Nothing)
Dts.Events.FireInformation(0, Component_Name, String.Format("TableA Data Updating"), "", 0, True)
Dts.TaskResult = Dts.Results.Success
Catch ex As Exception
Dts.Events.FireError(0, Component_Name, ex.Message, "", 0)
Dts.Log("Exception detected: " & ex.ToString, 0, Nothing)
Dts.TaskResult = Results.Failure
End Try
End Sub
Let's start by cleaning that up a little:
Public Sub Main()
Const Component_Name As String = "Updating TableA Data"
Const Conn_String As String = "Data Source=DB_A;Initial Catalog=TableA;Integrated Security=SSPI;"
Const sql_Emp As String = _
"UPDATE TableA" _
+ " SET Contract = c.License_No, SEIN = convert(varchar, c.Lic_Exp_Date, 101)" _
+ " FROM Server.DB_B.dbo.TableB c" _
+ " INNER JOIN TableA b" _
+ " ON rtrim(ltrim(c.business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))" _
+ " WHERE c.Lic_Exp_Date= (" _
+ " SELECT MAX(Lic_Exp_Date)" _
+ " FROM Server.DB_B.dbo.TableB" _
+ " WHERE rtrim(ltrim(business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))" _
+ ") AND convert(varchar, c.Lic_Exp_Date, 101) <> convert(varchar, b.SEIN, 101)"
Try
Using con As New SqlConnection(Conn_String), _
cmds New SqlCommand(sql_Emp, con)
Dts.Log("Opening DB Connection: " & con.ConnectionString, 0, Nothing)
con.Open()
cmd.ExecuteNonQuery()
Dts.Log(String.Format(Component_Name), 0, Nothing)
Dts.Events.FireInformation(0, Component_Name, String.Format("TableA Data Updating"), "", 0, True)
Dts.TaskResult = Dts.Results.Success
End Using
Catch ex As Exception
Dts.Events.FireError(0, Component_Name, ex.Message, "", 0)
Dts.Log("Exception detected: " & ex.ToString, 0, Nothing)
Dts.TaskResult = Results.Failure
End Try
End Sub
Okay, now that I can read it I can start looking at what might be broken. Check back in a few minutes for edits.
Okay, now let's look at that query. I'm missing some data type information, so I'm going to make some assumptions. Please correct any that are wrong:
b.Account_Key is some number type, probably int. Otherwise you wouldn't need to convert to varchar
The Lic_Exp_Date columns really are of type datetime
If those are correct, I think this will do what you want, but do it a lot faster:
UPDATE TableA
SET Contract = c1.License_No, SEIN = DATEADD(dd,0, DATEDIFF(dd,0, c1.Lic_Exp_Date))
FROM TableA b
INNER JOIN Server.DB_B.dbo.TableB c1
ON ISNUMERIC(c1.busines_lic) = 1 AND cast(c1.business_lic AS int) = b.Account_Key
INNER JOIN
(
SELECT business_lic, MAX(Lic_Exp_Date) AS Lic_Exp_Date
FROM Server.DB_B.dbo.TableB
GROUP BY business_lic, License_No
) c2 ON c2.business_lic = c1.business_lic AND c1.Lic_Exp_Date=c2.Lic_Exp_Date
WHERE DATEADD(dd,0, DATEDIFF(dd,0, c1.Lic_Exp_Date)) <> DATEADD(dd,0, DATEDIFF(dd,0, b.SEIN))
Here's what changed:
Turn the correlated subquery into a join. A join will be much faster, however the query optimizer might have been doing this for you already
Eliminate the need to call a number of per-row functions - should also help you match up with indexes better.
Use an integer comparison rather than string for your main join
Use date functions rather than convert to strings to remove the time portion, which should be much faster and in turn allow me to:
Use date comparisons rather than string comparisons in your join
The better way would be an Execute SQL task.