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

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

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

how can i fill a treeview from a database in vb.net?

i'm currently building an application that requires me to dynamically fill a tree view
i wrote the following code but the filling always stop at level 1
Private Sub TreeDraw(ByVal TreeRoot As String)
'Throw New NotImplementedException
TVNew.Nodes.Clear()
Dim con = New OleDbConnection(StrConn)
Dim strSql = "Select * from Tree WHERE TreeName = '" & _
TreeRoot.Trim & "' AND levelNum = 0" & _
" ORDER BY nodeID ASC"
Dim da = New OleDbDataAdapter(strSql, con)
Dim ds As New DataSet
Dim lvl = 0
Try
da.Fill(ds, "Tree")
Do While ds.Tables(0).Rows.Count > 0
If lvl = 0 Then
TVNew.Nodes.Add(ds.Tables(0).Rows(0)(4))
Else
For Each row As DataRow In ds.Tables(0).Rows
For Each node As TreeNode In TVNew.Nodes
If node.Text = row(3) Then
TVNew.SelectedNode = node
TVNew.SelectedNode.Nodes.Add(row(4))
End If
Next
Next
End If
'MsgBox(lvl.ToString)
lvl = lvl + 1
da.Dispose()
ds.Tables.Clear()
strSql = "Select * from Tree WHERE TreeName = '" & _
TreeRoot.Trim & "' AND levelNum =" & lvl & _
" ORDER BY nodeID ASC"
da = New OleDbDataAdapter(strSql, con)
da.Fill(ds, "Tree")
Loop
Catch ex As Exception
MsgBox(ex.Message & Chr(13) & da.SelectCommand.CommandText _
, vbOKOnly, Application.ProductName)
Exit Sub
End Try
TVNew.ExpandAll()
End Sub
can any one help please?

Error comparing datetime in 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.

Automation Error when executing SQL Server Script in Excel VBA

I am opening an SQL Server Connection in EXCEL VBA and on the objMyCmd.Execute line when it is using the SQL script I am getting this error message:
"Run-time error '-2147217900 (80040e14)') Automation error"
I have reviewed other SO posts that seem to reference an issue with the connection string itself, but I don't believe that is the issue as I am able to pull the first few variables listed when eliminating the rest of the SQL script.
I have attempted to review the SQL code to see if I am using an incorrect format, or if the language is not written properly and I am not able to determine the issue. I am hoping with some Q & A we may notice something I have missed in how this is written? Please let me know if there is additional information I can provide, below is the code up to the point of error.
Sub SQL_GetAgentChart()
Dim dtDate As Date
Dim myTable As ListObject
Dim DataServer As String
Dim Database As String
Dim constring As String
DataServer = "GLSSQLMADP2"
Database = "PERF_MGMT_BWRSRV_PROD"
constring = "Driver={SQL Server};Server=" & DataServer & "; Database=" & Database & "; Trusted_Connection=yes"
Dim AVStartDate As Date
Dim AVEndDate As Date
Dim RepID As Long
'Declare variables'
Set objMyConn = New ADODB.Connection
Set objMyCmd = New ADODB.Command
Set objMyRecordset = New ADODB.Recordset
Set myTable = Worksheets("Witness").ListObjects("tblWitness")
AVStartDate = DateValue("Mar 01, 2016")
AVEndDate = DateValue("Mar 31, 2016")
RepID = 2040
'Open Connection'
objMyConn.ConnectionString = constring
objMyConn.Open
'Set and Excecute SQL Command'
Set objMyCmd.ActiveConnection = objMyConn
objMyCmd.CommandText = " " & _
"SELECT PERSN_XTRNL_ID_NR, SOURCE, LOGGINGTS, DD7, CUREREASON, CUREDATE, LNSTATUS " & _
"FROM TTB " & _
"WITH INCALL AS (SELECT T.CUREREASON, CUREVALUE " & _
"FROM TTB T " & _
"JOIN PERSONNEL P ON T.PERSONNELID = P.PERSONNELID " & _
"LEFT JOIN CURETRANSLATE C ON T.CUREREASON = C.CUREREASON AND T.LNSTATUS = C.STATUS " & _
"WHERE T.PERSONNELID = " & RepID & " " & _
"AND LOGGINGTS > '" & AVStartDate & "' " & _
"AND LOGGINGTS < '" & AVEndDate + 1 & "' " & _
"AND INCOMING = 1 " & _
"AND DD7 > 0), OUTCALL AS (SELECT T.CUREREASON, CUREVALUE " & _
"FROM TTB T " & _
"JOIN AVAYA A ON T.UID = A.TTBUID " & _
"LEFT JOIN CURETRANSLATE C ON T.CUREREASON = C.CUREREASON AND T.LNSTATUS = C.STATUS " & _
"WHERE PERSONNELID = " & RepID & " " & _
"AND LOGGINGTS > '" & AVStartDate & "' " & _
"AND LOGGINGTS < '" & AVEndDate + 1 & "' " & _
"AND INCOMING = 0 " & _
"AND A.AVAYAGROUP IN ('15', '1A', '1B', '1C', '1D', '1E', '1F', '1G', '1H') " & _
"AND DD7 > 0) "
objMyCmd.CommandType = adCmdText
objMyCmd.Execute

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