I am using the standard ASP.NET Membership table structure in SQL Server and was doing a bit of manually querying in Management studio and ran this query
SELECT *
FROM [aspnet_Users]
WHERE UserId = '2ac5dd56-2630-406a-9fb8-d4445bc781da&cID=49'
Notice the &cID=49 at the end - I copied this from a querystring and forgot to remove that part.
However, to my surprise it returned the data correctly (there is a user with the ID 2ac5dd56-2630-406a-9fb8-d4445bc781da) - any idea why this works? To my mind it should not match or probably more likely throw an error as it shouldn't be able to convert to a Guid?
The uniqueidentifier type is considered a character type for the purposes of conversion from a character expression, and therefore is subject to the truncation rules for converting to a character type. That is, when character expressions are converted to a character data type of a different size, values that are too long for the new data type are truncated.
Because the uniqueidentifier type is limited to 36 characters, the characters that exceed that length are truncated.
Note that above is quoted from MSDN
The parser is (remarkably) lenient when converting string literals to guid literals, apparently:
SELECT CAST('E63F4FFC-8574-428B-B6B8-95CFCA05ED52' AS uniqueidentifier)
SELECT CAST('E63F4FFC-8574-428B-B6B8-95CFCA05ED52a' AS uniqueidentifier)
SELECT CAST('E63F4FFC-8574-428B-B6B8-95CFCA05ED52-!' AS uniqueidentifier)
SELECT CAST('E63F4FFC-8574-428B-B6B8-95CFCA05ED52~#5' AS uniqueidentifier)
SELECT CAST('E63F4FFC-8574-428B-B6B8-95CFCA05ED52$3%] ' AS uniqueidentifier)
all give the same result, no errors.
This is documented behaviour, so we can't really complain:
The following example demonstrates the truncation of data when the
value is too long for the data type being converted to. Because the
uniqueidentifier type is limited to 36 characters, the characters that
exceed that length are truncated.
DECLARE #ID nvarchar(max) = N'0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong';
SELECT #ID, CONVERT(uniqueidentifier, #ID) AS TruncatedValue;
Here is the result set.
String TruncatedValue
-------------------------------------------- ------------------------------------
0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong 0E984725-C51C-4BF4-9960-E1C80E27ABA0
(1 row(s) affected)
Related
I have a table with like this:
id
values
user_id
1
["8","7","6"]
5
Now I'm running a query with WHERE condition on values column:
SELECT * from table_name WHERE values = ["8","7","6"]
But MySQL returns this error:
Error Code : 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '["8","7","6"]'
If you want to compare for strict equality, you want to do the comparison as JSON objects. You can do this by using JSON_EXTRACT to parse the data as JSON instead of text:
SELECT * from table_name WHERE
JSON_EXTRACT(`values`, '$') = JSON_EXTRACT('["8","7","6"]', '$');
You should be able to use this for any type of JSON as long as you want strict equality. If you want to return all rows that match the given JSON object, use JSON_CONTAINS.
For example to find all values with the string "8" in it, you'd use the following:
SELECT * from table_name WHERE JSON_CONTAINS(`values`, '"8"');
Note that this matching is not as simple as you'd expect and matches any value in the document. If your data consists of JSON arrays, this should still be adequate.
The information about your column datatype, especially values are crucial. Since the column stores a mix of numbers and non-numbers characters, we can assume that it might be stored in VARCHAR() or TEXT datatype. But since the data format looks like a JSON array, it's also a possibility that the column datatype is JSON. Now both of these datatypes have a very different query structure.
First, let's address some issues:
Whenever the cell values include other characters than numerical, it will be considered as string. Hence, using plain .. WHERE values = ["8","7","6"] without wrapping it in quotes ('), you'll get that Error Code : 1064.
VALUES is a reserved word in MySQL so if you want to stick to it as your table column names, you always need to wrap it in backticks. If not, this will also return Error Code : 1064:
.. WHERE `values` = ..
Now let's try this:
If the column datatype for values is VARCHAR() or TEXT, you just have to simply wrap the search value in single quote like:
SELECT * from table_name WHERE `values` = '["8","7","6"]';
Refer this fiddle
updated for MariaDB
If the column datatype for values is JSON, it's something like this:
SELECT * from table_name where JSON_UNQUOTE(`values`)= '["8","7","6"]'
Refer this fiddle for JSON
The JSON method I've referred to this MariaDB documentation.
P/S: According to this documentation JSON is an alias for LONGTEXT introduced for compatibility reasons with MySQL's JSON data type. In other words, when creating a table with JSON datatype in MariaDB, it will be shown as LONGTEXT but with extra definition than just plain LONGTEXT datatype. See this fiddle for more detail.
In a React Native App I'm attempting to insert data into a local sqlite db
let submissionID = "1-2-3";
this.dbQuery("INSERT INTO Submissions (ID, Data) VALUES("+submissionID+",'Test')");
(dbQuery is the name of a function I made to simplify my queries but the statement inside it should be the same)
If I viewed the Submissions table after this insert statement I would expect to see a row with [ID:"1-2-3",Data:"Test"] but instead I see [ID:"-4",Data:"Test"]
I created the table like so
CREATE TABLE IF NOT EXISTS Submissions(ID BLOB PRIMARY KEY NOT NULL, Data BLOB NOT NULL)
I used Blob because I read "The value is a blob of data, stored exactly as it was input." but I've also tried Text. I've also casted submissionID as a string like so
this.dbQuery("INSERT INTO Submissions (ID, Data) VALUES("+String(submissionID)+",'Test')");
But none of that worked. I do see here how sqlite takes advantage of arithmetic operators
https://www.w3resource.com/sqlite/arithmetic-operators.php
but I'm not sure how to stop it from doing so.
How would I get sqlite to treat my hyphens as hyphens instead of subtraction signs?
What you're doing is the equivalent of:
this.dbQuery("INSERT INTO Submissions (ID, Data) VALUES(1-2-3,'Test')");
passing the numeric expression 1-2-3 to the INSERT statement. The simplest fix is to quote the string literal.
let submissionID = "1-2-3";
this.dbQuery("INSERT INTO Submissions (ID, Data) VALUES('"+submissionID+"','Test')");
However, to guard against SQL injection attacks, you really ought to be using prepared statements instead of using string concatenation to build SQL statements.
Enclose the string in single quotes i.e.
this.dbQuery("INSERT INTO Submissions (ID, Data) VALUES('"+String(submissionID)+"','Test')");
Thus the value is treated as a literal by SQLite, without enclosing the value it will either be treated as a numeric value or as an identifier (column, table, trigger, view depending upon where it is coded and thus what the parser expects).
The data type (column affinity) has little bearing other than if you specified ID INTEGER PRIMARY KEY, then you could not store anything other than an integer. As ID INTEGER PRIMARY key has a special interpretation that is the column is an alias of the rowid.
I used Blob because I read "The value is a blob of data, stored
exactly as it was input." but I've also tried Text. I've also casted
submissionID as a string like so
That is only if the value to be inserted is a BLOB byte[] or in the case of raw SQL x'FF01FE02', otherwise SQLite will store the value according to how it interprets the type should be stored.
I'm working on a small SQLite database using the Unix command line sqlite3 command tool. My schema is:
sqlite> .schema
CREATE TABLE status (id text, date integer, status text, mode text);
Now I want to set the column 'mode' to the string "Status" for all entries. However, if I type this:
sqlite> UPDATE status SET mode="Status";
Instead of setting column 'mode' to the string "Status", it sets every entry to the value that is currently in the column 'status'. Instead, if I type the following it does the expected behavior:
sqlite> UPDATE status SET mode='Status';
Is this normal behavior?
This is also a FAQ :-
My WHERE clause expression column1="column1" does not work. It causes every row of the table to be returned, not just the rows where column1 has the value "column1".
Use single-quotes, not double-quotes, around string literals in SQL. This is what the SQL standard requires. Your WHERE clause expression should read: column1='column2'
SQL uses double-quotes around identifiers (column or table names) that contains special characters or which are keywords. So double-quotes are a way of escaping identifier names. Hence, when you say column1="column1" that is equivalent to column1=column1 which is obviously always true.
http://www.sqlite.org/faq.html#q24
Yes, that's normal in SQL.
Single quotes are used for string values; double quotes are used for identifiers (like table or column names).
(See the documentation.)
I have a SQLite database with my Android application. I have noticed I accidentally defined a table using a "String" datatype instead of "Text" datatype. Here is the code with string:
private final String LISTDATES_CREATE = "create table if not exists ListDates (_id integer primary key autoincrement, ListName string not null, UpdateDate string not null);";
This works. It has never thrown an error and I can store and retrieve data. However I can't find any reference to a "String" datatype in SQLite in the documentation or on the internet. Typically, all string type data is defined with "text" like so:
private final String LISTDATES_CREATE = "create table if not exists ListDates (_id integer primary key autoincrement, ListName text not null, UpdateDate text not null);";
So my question is, what is the difference between a field defined with a "string" datatype versus a "text" datatype? Is there a difference? If so, what are the consequences, if any, of using one or the other?
This is an old question, but I want to highlight a specific difference between a STRING and TEXT column types. If a string looks like a numeric value, STRING will convert it into a numeric value, while TEXT will not perform any conversion.
e.g.
create table t1(myint INTEGER, mystring STRING, mytext TEXT);
insert into t1 values ('0110', '0220', '0330');
insert into t1 values ('-0110', '-0220', '-0330');
insert into t1 values ('+0110', '+0220', '+0330');
insert into t1 values ('x0110', 'x0220', 'x0330');
insert into t1 values ('011.0', '022.0', '033.0');
select * from t1
will output rows with values:
myint mystring mytext
110 220 0330
-110 -220 -0330
110 220 +0330
x0110 x0220 x0330
11 22 033.0
This means leading zeros, zeros trailing decimal points, and plus symbol on the "numeric" values will be stripped. This will cause problems if you intend on doing a string match using the values read out of the table.
The subtle thing to note here is that SQLite does not enforce the data type of values you put into columns. That means that you can put text into a numeric field, and so on.
To understand the difference between your two SQL statements, check out section 2.1 Determination Of Column Affinity, which maps the column types you provide to the storage classes SQLite uses.
In this case, the type string gets mapped to storage class NUMERIC via rule 5. Declaring the field as text in code would tell the DBMS to use the TEXT storage class. Again, since SQLite does not enforce the types of columns, your code will probably run fine when storing Strings as a NUMERIC column, as you note.
As an alternative example, you could define a column with type INTERESTING STUFF, and that would be mapped to the INTEGER storage class, via rule 1.
Overall, it's probably a good idea to just use text for your table definition.
I have 1,2,3,4,5,6,7,8,9 stored as nvarchar inside Level in my db.
I then have a dropdownlist with values 1,2,3,4,5,6,7,8,9. When a user makes a selection (i.e 1) (Level.SelectedValue.ToString). This builds an sql query via a param like this:
"Select things From MBA_EOI Where level = 1"
When I run the select I get the following error:
Syntax error converting the nvarchar value '1,2,3,4,5,6,7,8,9' to a column of data type int.
I was under the impression that I was dealing with an Nvarchar field and the selected value as string, where does the int conversion come in?
p.s I have also tried Level.SelectedItem.ToString
By including level = 1 you are implying to SQL that you want a numeric comparison, and it's attempting to cast all the column values to ints. If you used level = '1' instead, you'd get a text comparison with no conversion.