In ActiveRecord (using Ruby on Rails), if i have #products variable where #products = Product.all, and I say:
#products.where("name = 'check123' "), it returns an array of objects matching that condition, if i however go #products.where('name="check123"') i get an error?
: SELECT "products".* FROM "products" WHERE (name = "check123")
Hirb Error: PG::UndefinedColumn: ERROR: column "check123" does not exist
LINE 1: SELECT "products".* FROM "products" WHERE (name = "check123"...
^
Why is this happening? It seems that I must always use double quotes around everything in the where clause and single quotes for any strings inside there ?
Shouldn't single quotes work here as well, or is there something Im not getting
Some other observations:
#products.where("cost = '23.0'") works, event though 23 has a datatype of integer and not string?
#products.where('cost = 23') works, so I know i can use single quotes inside the where clause
NOTE: I am aware of using the '?' syntax inside the where clause to avoid sql injections, I am purposefully trying to execute the query like this.
Double quotes are used for naming database objects (table names, columns names, user names, schema names...) whilst single quotes are intended to represent strings to be used as values.
so your UndefinedColumn: ERROR makes sense as when filtering with #products.where('name="check123"') the SQL produced will be .... where name = "check123". The db engine is trying to find a column with the name check123 and match its value to the value of column name. As the column check123 does not exist in your table, you get an "undefined column name" error.
For your other question:
When you filter an integer column by a string value what happens is that the db engine does an implicit conversion of the column values to string in order to perform the search.
Update
The general SQL standard is described by this question's answers. In summary most Db engines follow most of the ANSI standard, and the use of double quotes is usually reserved for database objects.
Related
Does a regular INSERT INTO statement even work with TypeOrm? Tried formatting the string and quotes every which way, lost all patience.
await queryRunner.query('INSERT INTO "table"(column1,column2) VALUES ("Hi","Bye")');
Error: column "Hi" does not exist.
ie: it tries using the 1st value as the column lookup.
I also tried
await queryRunner.query('INSERT INTO "table"(column1,column2) VALUES ($1,$2) --PARAMETERS["Hi", "Bye"]');
Error: There is no parameter $1
Your problem come from the fact that you use double quotes for your string variable. As defined in the postgreSQL documentation, a string is an arbitrary sequence of characters bounded by single quotes ('). And farther in the documentation you can find that the double quotes (") are used to defined identifiers (such as table or column names)
This is very simple but somehow I'm doing something wrong with this query on my database.
I have this query below:
SELECT login FROM accounts WHERE login = "loginname";
When I execute this query the result I get is this:
column "loginname" does not exist
This is a no brainer, why is this query not working properly? I have a login column and I know that this user exists because I've found this person with the rails console. Why is the login criteria referring to itself as a column?
Try with single quotes '' if you are trying to match a string
SELECT login FROM accounts WHERE login = 'loginname';
Check the documentation
There is a second kind of identifier: the delimited identifier or
quoted identifier. It is formed by enclosing an arbitrary sequence of
characters in double-quotes ("). A delimited identifier is always an
identifier, never a key word. So "select" could be used to refer to a
column or table named "select", whereas an unquoted select would be
taken as a key word and would therefore provoke a parse error when
used where a table or column name is expected.
Double quotes (") are used to refer to object names, in a case sensitive way. In this case, "loginname" is interpreted as a column name, and the query fails, since there is no such column. In order to refer to a string literal, you should use single quotes ('):
SELECT login FROM accounts WHERE login = 'loginname';
-- Here ---------------------------------^---------^
It seems that the " " are the problem if you believe the documentation. Single quotes are required for string values.
From the PostgreSQL Documentation:
There is a second kind of identifier: the delimited identifier or quoted identifier. It is formed by enclosing an arbitrary sequence of characters in double-quotes ("). A delimited identifier is always an identifier, never a key word. So "select" could be used to refer to a column or table named "select", whereas an unquoted select would be taken as a key word and would therefore provoke a parse error when used where a table or column name is expected. The example can be written with quoted identifiers like this:
UPDATE "my_table" SET "a" = 5;
Quoted identifiers can contain any character, except the character with code zero. (To include a double quote, write two double quotes.) This allows constructing table or column names that would otherwise not be possible, such as ones containing spaces or ampersands. The length limitation still applies.
So in your query "loginname" is the same as having loginname without quotes - it's attempting to refer to a column with that name. To make it a literal string, use single-quotes instead.
I'm only beginning to learn SQL with SQLite3 so this question probably has a clear answer, which I just can't think of. I have a table called Books, which has the columns: name, author and price. When I type e.g. select name, price from Books where author = "A"; in sqlite3, it works just fine. However, when I make a .sql file with the following:
SELECT name, price
FROM Books
WHERE author = "A";`
and read the file in the same database, it reads
'Error: near line 1: no such column: "A"'
Any ideas?
Edit: I have also tried the same with single quotes (i.e. 'A') but it still gives the same error:
Error: near line 1: no such column: 'A'
Double quotes "A" are used as identifiers; you want to use single quotes 'A' for string literals. See the documentation for more information.
SELECT name, price FROM Books WHERE author = 'A';
The reason it worked in the first example is probably due to this:
If a keyword in double quotes (ex: "key" or "glob") is used in a
context where it cannot be resolved to an identifier but where a
string literal is allowed, then the token is understood to be a string
literal instead of an identifier.
I found the solution. I was using Mac's TextEdit program to write the SQL queries and it uses so called "smart quotes", which are not recognized as quotes by SQL. So I just changed the smart quote-setting off and all is well.
I tried to create table named 15909434_user with syntax like below:
CREATE TABLE 15909434_user ( ... )
It would produced error of course. Then, after I tried to have a bit research with google, I found a good article here that describe:
When you create an object in PostgreSQL, you give that object a name. Every table has a name, every column has a name, and so on. PostgreSQL uses a single data type to define all object names: the name type.
A value of type name is a string of 63 or fewer characters. A name must start with a letter or an underscore; the rest of the string can contain letters, digits, and underscores.
...
If you find that you need to create an object that does not meet these rules, you can enclose the name in double quotes. Wrapping a name in quotes creates a quoted identifier. For example, you could create a table whose name is "3.14159"—the double quotes are required, but are not actually a part of the name (that is, they are not stored and do not count against the 63-character limit). ...
Okay, now I know how to solve this by use this syntax (putting double quote on table name):
CREATE TABLE "15909434_user" ( ... )
You can create table or column name such as "15909434_user" and also user_15909434, but cannot create table or column name begin with numeric without use of double quotes.
So then, I am curious about the reason behind that (except it is a convention). Why this convention applied? Is it to avoid something like syntax limitation or other reason?
Thanks in advance for your attention!
It comes from the original sql standards, which through several layers of indirection eventually get to an identifier start block, which is one of several things, but primarily it is "a simple latin letter". There are other things too that can be used, but if you want to see all the details, go to http://en.wikipedia.org/wiki/SQL-92 and follow the links to the actual standard ( page 85 )
Having non numeric identifier introducers makes writing a parser to decode sql for execution easier and quicker, but a quoted form is fine too.
Edit: Why is it easier for the parser?
The problem for a parser is more in the SELECT-list clause than the FROM clause. The select-list is the list of expressions that are selected from the tables, and this is very flexible, allowing simple column names and numeric expressions. Consider the following:
SELECT 2e2 + 3.4 FROM ...
If table names, and column names could start with numerics, is 2e2 a column name or a valid number (e format is typically permitted in numeric literals) and is 3.4 the table "3" and column "4" or is it the numeric value 3.4 ?
Having the rule that identifiers start with simple latin letters (and some other specific things) means that a parser that sees 2e2 can quickly discern this will be a numeric expression, same deal with 3.4
While it would be possible to devise a scheme to allow numeric leading characters, this might lead to even more obscure rules (opinion), so this rule is a nice solution. If you allowed digits first, then it would always need quoting, which is arguably not as 'clean'.
Disclaimer, I've simplified the above slightly, ignoring corelation names to keep it short. I'm not totally familiar with postgres, but have double checked the above answer against Oracle RDB documentation and sql spec
I'd imagine it's to do with the grammar.
SELECT 24*DAY_NUMBER as X from MY_TABLE
is fine, but ambiguous if 24 was allowed as a column name.
Adding quotes means you're explicitly referring to an identifier not a constant. So in order to use it, you'd always have to escape it anyway.
What is the difference between single quotes and double quotes in SQL?
Single quotes are used to indicate the beginning and end of a string in SQL. Double quotes generally aren't used in SQL, but that can vary from database to database.
Stick to using single quotes.
That's the primary use anyway. You can use single quotes for a column alias — where you want the column name you reference in your application code to be something other than what the column is actually called in the database. For example: PRODUCT.id would be more readable as product_id, so you use either of the following:
SELECT PRODUCT.id AS product_id
SELECT PRODUCT.id 'product_id'
Either works in Oracle, SQL Server, MySQL… but I know some have said that the TOAD IDE seems to give some grief when using the single quotes approach.
You do have to use single quotes when the column alias includes a space character, e.g., product id, but it's not recommended practice for a column alias to be more than one word.
A simple rule for us to remember what to use in which case:
[S]ingle quotes are for [S]trings Literals (date literals are also strings);
[D]ouble quotes are for [D]atabase Identifiers;
Examples:
INSERT INTO "USERS" ("LOGIN", "PASSWORD", "DT_BIRTH") VALUES ('EDUARDO', '12345678', '1980-09-06');
In MySQL and MariaDB, the ` (backtick) symbol is the same as the " symbol. And note that you can't use " for literal strings when your SQL_MODE has ANSI_QUOTES enabled.
Single quotes delimit a string constant or a date/time constant.
Double quotes delimit identifiers for e.g. table names or column names. This is generally only necessary when your identifier doesn't fit the rules for simple identifiers.
See also:
Do different databases use different name quote?
You can make MySQL use double-quotes per the ANSI standard:
SET GLOBAL SQL_MODE=ANSI_QUOTES
You can make Microsoft SQL Server use double-quotes per the ANSI standard:
SET QUOTED_IDENTIFIER ON
In ANSI SQL, double quotes quote object names (e.g. tables) which allows them to contain characters not otherwise permitted, or be the same as reserved words (Avoid this, really).
Single quotes are for strings.
However, MySQL is oblivious to the standard (unless its SQL_MODE is changed) and allows them to be used interchangably for strings.
Moreover, Sybase and Microsoft also use square brackets for identifier quoting.
So it's a bit vendor specific.
Other databases such as Postgres and IBM actually adhere to the ansi standard :)
I use this mnemonic:
Single quotes are for strings (one thing)
Double quotes are for tables names and column names (two things)
This is not 100% correct according to the specs, but this mnemonic helps me (human being).
Two Things To Remember :
Single Qutoes(') : String Or Text
select * from employees where room_name = 'RobinCapRed';
where RobinCapRed is a string or a text.
Double Quotes(") : Column Names or Table Names
select "first_name" from "employees";
where first_Name is a column name from employees table
The difference lies in their usage. The single quotes are mostly used to refer a string in WHERE, HAVING and also in some built-in SQL functions like CONCAT, STRPOS, POSITION etc.
When you want to use an alias that has space in between then you can use double quotes to refer to that alias.
For example
(select account_id,count(*) "count of" from orders group by 1)sub
Here is a subquery from an orders table having account_id as Foreign key that I am aggregating to know how many orders each account placed. Here I have given one column any random name as "count of" for sake of purpose.
Now let's write an outer query to display the rows where "count of" is greater than 20.
select "count of" from
(select account_id,count(*) "count of" from orders group by 1)sub where "count of" >20;
You can apply the same case to Common Table expressions also.