Why does this SQL search give this incompatibility error? - sql-server

I'm having this error in my project when attempting to search using SQL for a specific name. When I type the name into a textbox and search.
This is the code used:
da = New SqlDataAdapter("select * From MovTable where NameOfMov = '" & NameSearchTB.Text & "'", sqlcon)
da.Fill(MovieSearchdt)
MovTable is the SQLDataTable
NameOfMov is the column I'm searching in.
This is the error appearing after attempting to search:
System.Data.SqlClient.SqlException: 'The data types ntext and varchar are incompatible in the equal to operator.'

The message is rather obvious. It has to with the table structure. The column NameOfMov seems to be ntext (Unicode text).
The name of a movie should fit in a varchar or nvarchar column so I doubt that ntext is a good choice here.
Some strategies are described here:
SQL SERVER – Fix: Error : 402 The data types ntext and varchar are incompatible in the equal to operator
Note that text/ntext are being deprecated:
IMPORTANT! ntext, text, and image data types will be removed in a future version of SQL Server. Avoid using these data types in new development work, and plan to modify applications that currently use them. Use nvarchar(max), varchar(max), and varbinary(max) instead.
Source: ntext, text, and image (Transact-SQL)
Another point repeated endlessly: always use parameterized queries. This code is unsafe (SQL injections) and will choke on characters like the single quote. This is not the way to do it in 2020.

If you cannot fix the datatype of field in your database as suggested by Anonymous in his answer then using parameters might work.
You should always use parameters to avoid Sql injection.
Private Function GetMovieData(NameToSearch As String) As DataTable
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string"),
cmd As New SqlCommand("select * From MovTable where NameOfMov = #Name;", cn)
cmd.Parameters.Add("#Name", SqlDbType.NText).Value = NameToSearch
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Usage:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dt = GetMovieData(NameSearchTB.Text)
DataGridView1.DataSource = dt
End Sub
This separates the User Interface code from the Data Access code. The button knows nothing about where the data is coming from and the GetMovieDate is not concerned with how or where the data is used.

Related

Problems with saving numbers after formatting example "200,000"

I try to save data from TextBox1.Text value to a SQL Server database in column of type Decimal(18, 0). I use VB.NET and SQL Server database.
I format the data in the textbox value to number for example "200,000".
When I try to save, I get this error
Error converting nvarchar to numeric
I can't use Val(Textbox1.text) because he take only "200" not "200000"
How can I fix this?
18 precision 0 scale is essentially a Long, so you should use Long.Parse() or Long.TryParse() to get the real numeric value in VB. This will give you more control than the antiquated Val() over things like separator characters.
Then, in the SQL part, make sure you're using a parameterized query with the appropriate type for the parameter:
Dim data As Long = Long.Parse(Textbox1.Text)
Dim sql As String = "INSERT INTO [someTable] (column) VALUES (#parameter)"
Using con As New SqlConnection("connection string here")
Using cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#parameter", SqlDbType.Decimal, 18, 0).Value = data
con.Open()
cmd.ExecuteNonQuery()
End Using

How to pass a date time value to SQL without a conversion error

I'm doing a windows form using Visual Basic.NET, SQL Server 2016, Visual Studio 2017.
I have been trying to fix this problem and already tried set dateformat mdy in SQL Server Management Studio query, but the dates on the table I have are still in this format: 2022-07-17 00:00:00.000. Does this have anything to do with this error when trying to insert something while running the project?
Everyone says stuff along the line "datetime doesn't work with yy/mm/dd or dd/mm/yy, use mm/dd/yy instead". But nobody says how you actually change/fix it in the database or Visual Studio.
I never found this error while using MySQL when I was studying and doing stuff on other languages, so this datetime thing is really getting desperate. Any insight on how to actually fix this error is greatly appreciated.
Code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim someid As Integer = TextCode.Text
Dim descri As String = TextDescription.Text
Dim somedate As DateTime = DateTimePickerinsert.Text
Dim value As String = TextValue.Text
Dim stock As String = TextStock.Text
Dim warehouse As String = ComboWarehouse.Text
con.Open()
Dim command As New SqlCommand("Insert into Item values('" & someid & "','" & descri & "','" & somedate & "','" & value & "','" & stock & "','" & warehouse & "')", con)
command.ExecuteNonQuery()
con.Close()
MessageBox.Show("Inserted succesfully")
LoadDataInGrid()
End Sub
I get
System.Data.SqlClient.SqlException: 'The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated.' error on the line: command.ExecuteNonQuery()
You should use proper parameterization, keeping your dates as actual DateTime values, rather than strings, likewise for numbers. Otherwise you will get SQL injection problems, this is not just a security issue but also about correctness.
The parameter values should be cast to the correct type before you send them, and the parameter objects should be declared with the correct SqlDbType and precision/length also.
You should also create and dispose your connection object, rather than keeping a global connection open, which is wasteful. Automatic connection pooling will ensure efficient usage of available connections.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim query As String = "
INSERT INTO Item (someid, descri, somedate, value, stock, warehouse)
VALUES (#id, #description, #date, #value, #stock, #warehouse)
"
Dim someid As Integer = Integer.Parse(TextCode.Text)
Dim somedate As DateTime = DateTimePickerinsert.Value
Dim value As Decimal = Decimal.Parse(TextValue.Text)
Dim stock As Integer = Integer.Parse(TextStock.Text)
Using con As new SqlConnection("YourConnectionString"),
command As New SqlCommand(query, con)
command.Parameters.Add("#id", SqlDbType.Int).Value = someid
command.Parameters.Add("#description", SqlDbType.VarChar, 100).Value = If(TextDescription.Text, DBNull.Value)
command.Parameters.Add("#date", SqlDbType.DateTime).Value = somedate
command.Parameters.Add("#value", SqlDbType.Decimal).Value = value
command.Parameters.Add("#stock", SqlDbType.Int).Value = stock
command.Parameters.Add("#warehouse", SqlDbType.VarChar, 50).Value = If(ComboWarehouse.Text, DBNull.Value)
con.Open()
command.ExecuteNonQuery()
End Using
MessageBox.Show("Inserted succesfully")
LoadDataInGrid()
End Sub
As far as viewing the results in SSMS: datetime values don't have an inherent format. SSMS will have a default way of displaying them, but you can show them any way you like by converting them using CONVERT, or in VB using ToString
You are seriously entertaining SQL Injection using that Code.
You don't directly insert data to SQL database from your Windows Controls.
Use SQL Connection Parameters to house the values.
That way, any text in the incoming data will not be evaluated as a SQL Script but a text literal.
Hackers could assign SQL Script to your TextDescription.Text
like "Exec 'Delete From XXX '"
and it will be executed.
Dim descri As String = TextDescription.Text
Use SQL Connection Parameters to house the values.
You may run into many issues while using strings as dates. If you are connecting to a stored procedure or just executing SQL via SqlClient or ODBC, one way to fix this error is to use Cast in your SQL string to convert the date string to something that the server will understand. ex:
Insert Into MyTable (MyID, MyDate) Values (#MyID, Cast(#MyDate as datetime));
or,
Insert Into MyTable (MyID, MyDate) Values (123, Cast('2022-03-14 14:12:00' as datetime));
It will be more forgiving on different formats that you might use.

Query SQL Server table with RowVersion

I am querying SQL Server from VBA using ADODB. All of my tables have RowVersion (timestamp/varbinary) columns. Since VBA doesn't support the varbinary type, I convert the RowVersion to a string from a SQL Server function. A simple query will look like:
sql = "SELECT NameValueListID, dbo.RowVersionToString(RowVersion) AS RowVersion FROM NameValueLists WHERE NameValueListID=1
To get the data onto a sheet, I first tried range.CopyFromRecordset. This worked until I included the above function in the sql call. Adding the RowVersionToString function caused the recordset to return what seems like a random set of data - less rows than excepted and fewer column than I asked for. Never could figure that one out. I then used rs.GetRows which returned the expected data and I could use range.value = rsData successfully. Below is a sample call that works.
Private Sub Test_Scratch()
Dim rs As ADODB.Recordset
Dim sqlCmd As New ADODB.Command
Dim sqlConnection As ADODB.Connection
Dim sql As String
Dim rsData() As Variant
Set sqlConnection = New ADODB.Connection
sqlConnection.Open ModSQL.GetConnectionStringByStage(wsSetup.Range("suAppStage"))
sql = "SELECT NameValueListID, dbo.RowVersionToString(RowVersion) AS RowVersion FROM NameValueLists WHERE NameValueListID=1"
Set sqlCmd.ActiveConnection = sqlConnection
sqlCmd.CommandText = sql
Set rs = sqlCmd.Execute
rs.MoveFirst
rsData = rs.GetRows
End Sub
I then added a second varbinary column to the query (it's not a RowVersion but is of the same type). So the sql will look like:
sql = "SELECT NameValueListID, dbo.RowVersionToString(RowVersion) AS RowVersion, dbo.RowVersionToString(LastItemRowVersion) AS LastItemRowVersion FROM NameValueLists WHERE NameValueListID=1
After the call, the recordset rs has all the data, but rsData has "Empty" for the first varbinary column. The order doesn't matter. Only the last varbinary column has a value, the other is always "Empty" in the rsData array.
I guess,more could anser your question if you showed your code of user function RowVersionToString.What is the definition of argument of RowVersionToString?It might be that the argument "RowVersion" was interpreted to a data type not but a colmun name.
sql = "SELECT NameValueListID, dbo.RowVersionToString(NameValueLists.RowVersion) AS RowVersion, dbo.RowVersionToString(LastItemRowVersion) AS LastItemRowVersion FROM NameValueLists WHERE NameValueListID=1

vb.net ms access mdb table insert record code not works

I want to insert data into MS Access database (mdb) table. The code is shown below:
Imports System.Data.OleDb
Imports System.Data
Dim Cmd As OleDbCommand
Dim SQL As String
Dim objCmd As New OleDbCommand
Dim Con = New OleDbConnection("Provider=Microsoft.ace.oledb.12.0; Data Source=" & pth & "\database.mdb; User Id=; Password=;")
MsgBox(RichTextBox1.SelectedText)
SQL = "insert into approved ( word, approveds) VALUES ('" & RichTextBox1.SelectedText & "', " & "'YES')"
MsgBox(SQL)
Cmd = New OleDbCommand(SQL, Con)
Con.Open()
objCmd = New OleDbCommand(SQL, Con)
objCmd.ExecuteNonQuery()
Con.Close()
It shows following error message
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: Data type mismatch in criteria expression.
Can any one please help
Or any other procedure
First thing's first.
What do you expect " & "'YES' to mean ? Correct me if i'm wrong but you want to pass Yes as the value ? Or maybe even "Yes"(with quotes) ?
If it's the first one, only Yes inside single quotes would be enough('Yes'). For the second case, it would be '\"Yes\"'.
There are still too many issues with your code. You are using & operator to concatenate strings. Some might argue that there's no problem with using & but look at the code and tell me what's your first expression? Well, my first expression was :
That looks ugly!
So, instead of concatenation, you could simply format the string. Of course the results are the same, yet string formatting would look cleaner and more professional. Here's a sample :
Dim x as String = "My Name Is {0}."
Dim MyName As String = String.Format(x, "Zack Raiyan")
Now comes MsgBox(SQL). Well, i don't need a second guess for this, you are using this line to see if your sql statement is as expected. If that's the case, why not just put a breakpoint ?
Now, let's talk about your variable declarations. Why declare a variable without initializing it with any instance but later on, just after a few lines of code, initialize it when this could've been done in the first place ? Sample :
Dim x As New ObjectX
Instead of
Dim x As Object
.....
.....
x = New Object()
Finally, if you are getting to frustrated reading all these suggestions, let's talk about the main culprit here, your sql statement.
insert into approved ( word, approveds)
A space before and after the parenthesis may not make any difference but why use them at all? You may be new in programming but understand this:
You would spend 20% of your time in writing code and 80% of your time in maintaining it.
So, always write clean, simple & reusable codes.
Moving on....
VALUES ('" & RichTextBox1.SelectedText & "')
Don't do this! Instead pass parameters and then pass values to them. A quick example :
Dim sql = New SqlCommand("Insert Into TableX(Column1)Values(#Column1Val)", MySqlConnection)
sql.Parameters.Add("#Column1Val", SqlDbType.VarChar).Value = "XYZ"
There's a shorter way tho :
sql.Parameters.AddWithValue("#Column1Val", "XYZ")
but only use it when you know that you are passing a value of the same data type as the column you are passing it to.
I explained as much i could. I hope you understand your mistakes and also hope that you don't fail to see how my answer addresses the exception you are getting. If you are still unclear, leave a comment and i would be happy to help.
Just a small addition to #zack raiyan 's code. That is the Using block which will close and dispose your connection. This is important with connection objects because they use unmanaged code.
I am guessing that since your error is a data type mismatch that the problem might be with the approveds column. If this is a Yes/No column then it should be safe to use True for the value.
Check the data types of the 2 parameters in your database table and adjust the code appropriately.
Private Sub AddRecord(pth As String)
Dim SQL = "insert into approved ( word, approveds) VALUES (#word, #approval)"
Using Con As New OleDbConnection("Provider=Microsoft.ace.oledb.12.0; Data Source=" & pth & "\database.mdb; User Id=; Password=;")
Dim Cmd As New OleDbCommand(SQL, Con)
Cmd.Parameters.Add("#word", OleDb.OleDbType.VarChar).Value = RichTextBox1.SelectedText
Cmd.Parameters.Add("#approval", OleDbType.Boolean).Value = True
Con.Open()
Cmd.ExecuteNonQuery()
End Using
End Sub

Sql select statement with two conditions in visual basic

I am trying to retrieve Two Columns; App_ID & App_Slot from a table su_Appointments from an sql server database using vb, and I have two conditions the Date and Time; App_Date & App_Time for the query, now when I run the query it throws an error saying : Incorrect syntax near '2014'. The query is as follows
I am going to store App_ID into the variable AP_ID
CODE
Using Query As New SqlCommand("Select App_ID From su_Appointments Where (App_Date = ' and App_Time = ' )" & DT & TM, sqlcon)
sqlcon.Open()
Dim dr As SqlDataReader = Query.ExecuteReader()
While dr.Read()
AP_ID = dr(0)
End While
End Using
sqlcon.Close()
Well, your syntax is effectively wrong
A SELECT statement requires
SELECT <fieldA>, <FieldB>, ....
FROM <Table>
WHERE <FieldX> = <Condition1> AND <FieldZ> = <Condition2>
But, a part from this basic error, you need to start using a parameterized query approach
Using sqlcon = new SqlConnection(.....connectionstring...)
Dim cmdText = "Select App_ID From su_Appointments Where App_Date =#dt and App_Time = #tm"
Using Query = New SqlCommand(cmdText, sqlcon)
sqlcon.Open()
Query.Parameters.AddWithValue("#dt", DT)
Query.Parameters.AddWithValue("#tm", TM)
Using dr =Query.ExecuteReader()
While dr.Read()
AP_ID = dr(0)
End While
End Using
End Using
End Using
With a parameterized query, you get many benefits. There is no possibility of Sql Injection Attacks, the text of your command is more clear and understandable, the parameters are treated for correct quoting by the code itself so you don't need to check for single quotes inside your strings, or format correctly dates and decimal numbers.
Eventually, you could encounter a different problem. If your columns App_Date and App_Time are of type datetime then you need to pass parameters of the appropriate type, not simply strings. Instead if, these fields are of type nvarchar (or some other kind of text type) then you pass strings but you will have problems storing and querying correctly in these fields.

Resources