Error comparing datetime in SQL Server - sql-server

I'm currently writing this program that the user will input the start date and end date. Then the program will retrieve the records from the database where the startdate in db will be >= user input start date and enddate in db will be <= user input end date.
Dim dateStr As DateTime = dtpStart.Value
Dim dateEnd As DateTime = dtpEnd.Value
MsgBox(dateStr)
con.ConnectionString = "Data Source=MKZSA065\SQLSERVER2008R2,1499;Initial Catalog=inv"
con.Open()
MsgBox("server connected")
cmd.Connection = con
'cmd.CommandText = "Select column_name as 'Columnname', data_type as'Datatype' from information_schema.columns where table_name = 'inv.dbo.InOutTransaction' AND column_name = 'inv.dbo.InOutTransaction.startDate'"
'cmd.CommandText = "Select inv.dbo.InOutTransaction.refNo, inv.dbo.Case_Status.deployedBy, CONVERT(varchar(10), inv.dbo.InOutTransaction.startDate, 120) as startDate, CONVERT(varchar(10), inv.dbo.InOutTransaction.endDate, 120) as endDate, inv.dbo.InOutTransaction.item FROM inv.dbo.InOutTransaction inner join inv.dbo.Case_Status ON inv.dbo.InOutTransaction.refNo = inv.dbo.Case_Status.refNo WHERE inv.dbo.InOutTransaction.refNo LIKE 'L%' AND inv.dbo.InOutTransaction.status LIKE 'Out'"
cmd.CommandText = "Select inv.dbo.InOutTransaction.refNo, inv.dbo.Case_Status.deployedBy, CONVERT(varchar(10),inv.dbo.InOutTransaction.startDate,120) as startDate, CONVERT(varchar(10),inv.dbo.InOutTransaction.endDate,120) as endDate, inv.dbo.InOutTransaction.item from inv.dbo.InOutTransaction inner join inv.dbo.Case_Status ON inv.dbo.InOutTransaction.refNo = inv.dbo.Case_Status.refNo WHERE inv.dbo.InOutTransaction.refNo LIKE 'L%' AND inv.dbo.InOutTransaction.status LIKE '%Out%' AND inv.dbo.InOutTransaction.startDate >= '" & dateStr & "' AND inv.dbo.InOutTransaction.endDate <= '" & dateEnd & "'"
Dim lrd As SqlDataReader
Dim li As ListViewItem
lrd = cmd.ExecuteReader()
Dim num As Integer = 1
While lrd.Read()
ListView1.BeginUpdate()
li = ListView1.Items.Add(num.ToString)
li.SubItems.Add(lrd("refNo").ToString)
li.SubItems.Add(lrd("deployedBy").ToString)
li.SubItems.Add(lrd("startDate").ToString)
li.SubItems.Add(lrd("endDate").ToString)
li.SubItems.Add(lrd("item").ToString)
'li.SubItems.Add(lrd("column_name").ToString)
'li.SubItems.Add(lrd("data_type").ToString)
num += 1
ListView1.EndUpdate()
ListView1.EnsureVisible(ListView1.Items.Count - 1)
End While
There was an error
Conversion failed when converting datetime from character string
How and what should I do :(

USE PARAMETERISED QUERIES
Sorry to yell, but I cannot stress enough how important this is, not just to resolve your error, but for performance, and security of your application in general.
So instead of
"inv.dbo.InOutTransaction.startDate >= '" & dateStr & "' AND inv.dbo.InOutTransaction.endDate <= '" & dateEnd & "'"
You need to use
"inv.dbo.InOutTransaction.startDate >= #StartDate AND inv.dbo.InOutTransaction.endDate <= #EndDate"
Then add the parameters to your SqlCommand:
cmd.Parameters.Add("#StartDate", SqlDbType.DateTime).Value = dateStr
cmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = dateEnd
This means that there is no need for any implicit conversions, your SqlCommand is expecting two date parameters, and you pass two DateTime objects. All of a sudden the format of the dates, and cultural variations is irrelevant. Furthermore, it means that SQL Server can make use of cached plans and does not need to recompile the query for every different start and end date values passed.
As an aside, it is a good idea to use Using when dealing with IDisposable objects, especially with unmanaged objects like these. So you might end up with something like:
Dim dateStr As DateTime = dtpStart.Value
Dim dateEnd As DateTime = dtpEnd.Value
Dim sql as String = "Select inv.dbo.InOutTransaction.refNo, " & _
" inv.dbo.Case_Status.deployedBy, " & _
" CONVERT(varchar(10), " & _
" inv.dbo.InOutTransaction.startDate,120) as startDate, " & _
" CONVERT(varchar(10),inv.dbo.InOutTransaction.endDate,120) as endDate, " & _
" inv.dbo.InOutTransaction.item " & _
"from inv.dbo.InOutTransaction "
" inner join inv.dbo.Case_Status " & _
" ON inv.dbo.InOutTransaction.refNo = inv.dbo.Case_Status.refNo " & _
"WHERE inv.dbo.InOutTransaction.refNo LIKE 'L%' " & _
"AND inv.dbo.InOutTransaction.status LIKE '%Out%' " & _
"AND inv.dbo.InOutTransaction.startDate >= #StartDate " & _
"AND inv.dbo.InOutTransaction.endDate <= #EndDate"
Using con As new SqlConnection("Data Source=MKZSA065\SQLSERVER2008R2,1499;Initial Catalog=inv;User ID=inv_admin;Password=inv_admin123")
Using cmd As New SqlCommand(sql, con)
con.Open()
cmd.Parameters.Add("#StartDate", SqlDbType.DateTime).Value = dateStr
cmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = dateEnd
Using lrd As SqlDataReader = cmd.ExecuteReader()
Dim num As Integer = 1
Dim li As ListViewItem
While lrd.Read()
ListView1.BeginUpdate()
li = ListView1.Items.Add(num.ToString)
li.SubItems.Add(lrd("refNo").ToString)
li.SubItems.Add(lrd("deployedBy").ToString)
li.SubItems.Add(lrd("startDate").ToString)
li.SubItems.Add(lrd("endDate").ToString)
li.SubItems.Add(lrd("item").ToString)
'li.SubItems.Add(lrd("column_name").ToString)
'li.SubItems.Add(lrd("data_type").ToString)
num += 1
ListView1.EndUpdate()
ListView1.EnsureVisible(ListView1.Items.Count - 1)
End While
End Using
End Using
Please forgive my vb.Net if it is littered with errors, I haven't used it in a long time so am rusty to say the least, hopefully it is good enough to get the point across though

I would imagine the the datestr is in a local format.
Use the format YYYYMMDD as that is consistent regardless of DATEFORMAT settings.

Related

Pass date range in rdlc report vb.net

Need help
I am using sql server 2016, visual studio 2017
In my report i am unable to pass date range, when report is loading its showing all records from beginning to till date, where am mistake pls help!!
Below code is am made in 1 function and calling on button click
Dim strSQL As String = "", strSQLID As String = "", strSQLOrderBy As String = ""
Dim query As String = " select o.InvoiceDate,o.RegistrationNo,o.PatientName,o.TransactionStatus,o.gender,o.company,o.Visittype,o.Doctor,o.Specialisation,"
query &= " o.departmentName,o.Address,o.CityName,o.StateName,o.MobileNo,o.ServiceName"
query &= " from DRT_VW_OPVISIT o "
query &= " inner join employee e on o.DoctorId=e.ID "
'query &= " where e.ID in ('') "
query &= " where convert(varchar,o.InvoiceDate,111) between '" + DateTimePicker1.Text + " ' and '" + DateTimePicker2.Text + "' "
query &= " and o.TransactionStatus='Active' "
'query &= " order by InvoiceDate desc "
If Trim(strID) <> "" Then strSQLID = strSQLID & " And e.ID In (" + strID + ")"
strSQLOrderBy = " order by o.InvoiceDate desc "
conn = GetConnect()
conn.Open()
query = query & strSQLID & strSQLOrderBy
Dim cmd As SqlCommand = New SqlCommand(query, conn)
MsgBox(query)
cmd.Parameters.AddWithValue("DateTimePicker1", Me.DateTimePicker1.Value)
cmd.Parameters.AddWithValue("DateTimePicker2", Me.DateTimePicker2.Value)
Dim sda1 As SqlDataAdapter = New SqlDataAdapter(cmd)
Dim ds1 As New DataSet1
Dim dt2 As DataTable = New DataTable()
sda1.Fill(dt2)
With RepDoctorWiseVisit.ReportViewer1.LocalReport
.ReportPath = "D:\VB Project 2021\RepDepartmentWisePrice\RepDepartmentWisePrice\Report3.rdlc"
.DataSources.Clear()
.DataSources.Add(New Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", dt2))
End With
RepDoctorWiseVisit.Show()
RepDoctorWiseVisit.ReportViewer1.RefreshReport()
Return dt2
```
You've got a number of different things in your sample code that will cause you some issue. You need to do some reading on using Sql Parameters in your TSQL commands. As pointed out by Larnu, security is an issue but the real benefit to you as a developer is it is a million times easier to debug.
I've also made an assumption here DRT_VW_OPVISIT.InvoiceDate is a DateTime column in your DB.
Anyway, try this for a start
Also, just a note. If it is a Date Time, you will in all likelihood need to adjust for the time component
Dim strSQL As String = "", strSQLID As String = "", strSQLOrderBy As String = ""
Dim query As String = " select o.InvoiceDate,o.RegistrationNo,o.PatientName,o.TransactionStatus,o.gender,o.company,o.Visittype,o.Doctor,o.Specialisation,"
query &= " o.departmentName,o.Address,o.CityName,o.StateName,o.MobileNo,o.ServiceName"
query &= " from DRT_VW_OPVISIT o "
query &= " inner join employee e on o.DoctorId=e.ID "
query &= " where o.InvoiceDate between #DateTimePicker1 and #DateTimePicker2 "
query &= " and o.TransactionStatus='Active' "
If Trim(strID) <> "" Then strSQLID = strSQLID & " And e.ID In (" + strID + ")"
strSQLOrderBy = " order by o.InvoiceDate desc "
conn = GetConnect()
conn.Open()
query = query & strSQLID & strSQLOrderBy
Dim cmd As SqlCommand = New SqlCommand(query, conn)
MsgBox(query)
cmd.Parameters.Add("#DateTimePicker1", SqlDbType.DateTime).Value = Me.DateTimePicker1.Value
cmd.Parameters.Add("#DateTimePicker2", SqlDbType.DateTime).Value = Me.DateTimePicker2.Value
Dim sda1 As SqlDataAdapter = New SqlDataAdapter(cmd)
Dim ds1 As New DataSet1
Dim dt2 As DataTable = New DataTable()
sda1.Fill(dt2)
With RepDoctorWiseVisit.ReportViewer1.LocalReport
.ReportPath = "D:\VB Project 2021\RepDepartmentWisePrice\RepDepartmentWisePrice\Report3.rdlc"
.DataSources.Clear()
.DataSources.Add(New Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", dt2))
End With
RepDoctorWiseVisit.Show()
RepDoctorWiseVisit.ReportViewer1.RefreshReport()
Return dt2
I Will also warn you, there are a number of other improvements you can make, things like wrapping your connection in a "Using" block will keep that clean. And don't get me started on the hard coded report path.
I'm not saying this is a complete answer, but hopefuly I've given you the info to go get what you need yourself

INSERT or UPDATE a record in SQL from VBA

I have put together some code in VBA which exports data from an excel sheet to a Data Base, this code (below) currently just inserts the data, but I would like to insert it based on a key (the date). So if the date already exists then in the DB the record associated with that date is replaced, if the date does not already exist, then it is inserted as usual.
Current code:
Sub SendData(AB As String, CD As String, EF As String, GH As String, IJ As String, KL As Double, MN As Double, PQ As Double, RS As Double)
Dim Date As String, Entity As String, area As String, unit As String, name As String, surname As String
Dim day As Double, weekly As Double, month As Double, year As Double
Dim objConn As ADODB.Connection
Set objConn = New ADODB.Connection
objConn.ConnectionString = "Provider=SQLOLEDB;Data Source=source;Initial Catalog=Title;Integrated Security=SSPI"
objConn.Open
Set objRec = New ADODB.Recordset
Date = Format(Range("date").Value, "YYYY-MM-DD")
Entity = AB
area = CD
unit = EF
name = GH
surname = IJ
daily = KL
weekly = MN
month = PQ
year = RS
StrSQL = "insert into table_name values ('" & Date & "', '" & Entity & _
"','" & area & "','" & unit & "','" & name & "','" & surname & "'," & daily & "," & weekly & "," & month & "," & year & ")"
Set objRec = objConn.Execute(StrSQL)
objConn.Close
Set objConn = Nothing
end sub
I am a bit confused where to place the key...
Thanks
You can do something like
StrSQL = "SELECT * FROM table_name"
objRec.Open StrSQL, objConn, , adLockOptimistic
objRec.Find "[date_value] = #" & Date & "#",,,adBookmarkFirst
If objRec.EOF Then
objRec.AddNew "[date_value] = #" & Date & "#"
End If
objRec![Entity] = Entity
'repeat for all required fields
objRec.Update
objRec.Close
I'm not 100% sure there is no minor error, as I "translated" it from my own working code, but general idea and instructions should be correct. This way you leverage recordset mechanics. I'm not sure about performance, maybe somebody more advanced will criticize it for being slow, but it works for me.
Look at sql joins you can do a join for the update and then another for the insert, if you are doing an entire range, if not use something like select count(ID) from [table_name] where [date_value]='your date' and use an if statement based on the resultant recordsets recordcount or do a select [date_value] from [table_name] of the destination table at the start of the proc in a separate rst and use .find to see if it's there
For one thing, I would change that 'Date' to something like 'TheDate', or some other descriptive, but non-reserved kind of word. Also, insert is insert and update is update. The Update (not insert) should be something like this:
StrSQL = "UPDATE table_name SET values ('" & Date & "', '" & Entity & _
"','" & area & "','" & unit & "','" & name & "','" & surname & "'," & daily & "," & weekly & "," & month & "," & year & ")
WHERE " & sWhere
Or, consider using the MERGE clause.

vb.net - using a CTE Query in VB.net?

I have a working SQL Query with a CTE and I need that query in my vb.net application, but the problem is I get an error that states:
"Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'"
and the code is like this:
Dim da As New OleDbDataAdapter
Dim ds As New DataSet
Dim dt As New DataTable
Dim sqlcmd As String = (";WITH q AS
(
SELECT a.*
FROM SampleData AS a
WHERE EXISTS (SELECT 1
FROM SampleData AS b
WHERE a.Name = b.Name
AND a.Account= b.Account
AND a.Amount = -b.Amount)
)
DELETE FROM q OUTPUT DELETED.* INTO SampleData2")
If connDB.State = ConnectionState.Closed Then
connDB.Open()
End If
Try
ds.Tables.Add(dt)
da = New OleDbDataAdapter(sqlcmd, connDB)
da.Fill(dt)
Any help on this? I can't find any solution to this.
Here is my function that works with a simple CTE, use this function to test your expression, just replace your CTE in it and see, you might need fix your query.
Public Sub RecursiveData()
Dim connectionString As String = "Initial Catalog=DBName;Data Source=ServerName;uid=user;password=mypassword;Connection Timeout=50000"
Dim cteQuery As String = ";WITH cte " & vbCrLf &
" AS(SELECT 1 AS n " & vbCrLf &
" UNION ALL " & vbCrLf &
" SELECT n + 1 " & vbCrLf &
" FROM cte " & vbCrLf &
" WHERE n <50 " & vbCrLf &
" ) " & vbCrLf &
" SELECT n " & vbCrLf &
" FROM cte where n <= 5; "
Using _con As New SqlConnection(connectionString)
Using _cmd As New SqlCommand(cteQuery, _con)
_con.Open()
Using rdr As SqlDataReader = _cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr.GetValue(0).ToString())
End While
rdr.Close()
End Using
_con.Close()
End Using
End Using
End Sub

I want to automate the starting and ending date that are provided from the user on a excel sheet

I want to automate the starting and ending date that are provided from the user on a excel sheet. Below is the code I have so far:
Sub Button1_Click() ; formatted
Dim startDate As Date
Dim endDate As Date
startDate = Worksheets("sheet1").Range("B4").Value
endDate = Worksheets("sheet1").Range("B6").Value
dbConnectStr = "Provider=xxdose;User Id=" & Uname
dbConnectStr1 = "Provider=xxdose;User Id=xxtrece ;Data Source=" & DSN
Worksheets("WorkFlow").Activate
ActiveSheet.Range("B4:C30000").Clear
'Set and Execute SQL Command
Set Sql.ActiveConnection = objmyconn
Sql.CommandText = "select system_date from syit_act_log where system_date between`enter code here` 'startDate' AND 'endDate' and action_id = 15 and log_desc not like '%svc_openlink_p%' order by system_date"
Sql.CommandType = adCmdText
Sql.Execute
Next
ActiveSheet.Range("B5").CopyFromRecordset (ds)
ActiveSheet.Range("A1").Select
End Sub
Give this a shot, as mentioned in my comment, you must escape the variables to add them as part of the SQL statement string you are building.
"select system_date from syit_act_log where system_date >= #" & StartDate & _
"# and system_date <= #" & EndDate & "# and action_id = 15 and log_desc not like '%svc_openlink_p%' order by system_date"

SSIS Update Table Values from Another Table

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.

Resources