Alternate Postgres syntax for escaping reserved words - sql

In a PGSQL query one might use double-quotes to escape a column or table name that happens to be a reserved word, like so
select "name" from sometable;
This is often combined with C#, and the escaping must itself be escaped.
string sql = "select \"name\" from sometable;";
However, there is another C# trick that I would like to use to allow line breaks in my SQL for legibility, like so:
string sql = #"
select
foo
from
sometable;";
And here we come unglued: you can't use backslashes to escape double-quotes in a string in which backslashes and linebreaks are treated as literals.
Generally I exploit the fact that dot notation makes the escaping unnecessary.
string sql = #"
select
x.name
from
sometable as x;";
But what of tables with reserved words for names?
string sql = #"
select
foo
from
user;";
Putting aside my burning desire to thump the person who keeps using reserved words for column and table names, I ask for alternate syntax. I tried the widely used square bracket syntax.
string sql = #"
select
foo
from
[user];";
But PGSQL seems to be unhelpful there.
I did find a workaround: dot notation again.
string sql = #"
select
foo
from
public.user;";
But the question stands: alternate notation?

There is no alternative to double quotes for quoting identifiers. You will have to pay the price for the bad design choice of choosing identifiers that are not standard compliant.

Related

Pull variables with spaces in between for SQL table using RODBC's sqlQuery

In my SQL Server database table there is one variable with spaces. I am trying to write one query in the RODBC::sqlQuery function but I am not able to use this variable.
I tried to use single quotes but that doesn't work.
I tried to use paste option and create one string for query but even that also did not work.
Following is the query:
p5 <-sqlQuery(con, 'SELECT
a.region,
a.Country,
a.Qtr_ID,
Net_VAT AS Variable_Type,
"Printing" AS [External_Segment],
SUM(a.VR_Value) AS Value
FROM
(SELECT
d.region,
d.Country,
dt.Qtr_ID,
SUM([Actuals YTD] / 1000000) AS VR_Value
FROM ZOOM_DATAMART.dbo.[New_BalSheet_Fact] a
INNER JOIN [dbo].[Buss_Area_Dim_V] b
ON a.Bus_Area_ID = b.Bus_Area_ID
AND b."GBU External Segment Description" = "Printing"
INNER JOIN [dbo].[BSR_Header_GA_Dim_V] c
ON a.BSR_HEADER_GA_KEY = c.BSR_HEADER_GA_KEY
AND c.[Group Account Identifier] IN (1291, 2150, 2151,
2152, 2153, 2154)
INNER JOIN [dbo].[Legal_Company_Dim_V] d
ON a.Legal_Cmp_Key = d.Legal_Cmp_Key
INNER JOIN dbo.Date_Dim dt
ON a.Date_key = dt.Date_key
AND dt.Max_month_Flag = 1
GROUP BY d.region,
dt.Qtr_ID,
d.Country
) a
GROUP BY a.region,
a.Country,
a.Qtr_ID)
The issue is happening with "GBU External Segment Description". I get following error:
chr [1:4] "42S22 207 [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'Printing'." ...
Then I removed double quote from printing but still for "GBU External Segment Description" it doesn't accept and throws following error:
chr [1:3] "42000 102 [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'GBU External Segment Description'." ...
The error is not with the fieldname I believe, but with the varchar constant that you are looking for. You should be using single quotes, not double.
This:
a.Bus_Area_ID = b.Bus_Area_ID and b."GBU External Segment Description"= "Printing"
Should be this:
a.Bus_Area_ID = b.Bus_Area_ID and b.[GBU External Segment Description] = 'Printing'
Generally, String values in SQL are not wrapped in double quotes, but single quotes.
Also, in your first line:
p5 <-sqlQuery(con,'SELECT a.region,a.Country,a.Qtr_ID,Net_VAT as Variable_Type,"Printing" as [External_Segment]
Are you trying to output Printing as a constant result from this query? If so, and it is not a field name, then you should also wrap that in ' single quotes, not double. That is likely what is cauing the first error that you are seeing.
So that it becomes:
p5 <-sqlQuery(con,'SELECT a.region,a.Country,a.Qtr_ID,Net_VAT as Variable_Type,'Printing' as [External_Segment]
The previous comment on your question about wrapping fieldnames with [] is correct, you should use [] the square brackets to wrap field names with spaces in them.
This query should work:
p5 <-sqlQuery(con,'SELECT a.region,a.Country,a.Qtr_ID,Net_VAT as Variable_Type,\'Printing\' as [External_Segment]
,SUM(a.VR_Value) as Value
from
(SELECT d.region,d.Country,dt.Qtr_ID
,sum([Actuals YTD]/1000000) as VR_Value
FROM ZOOM_DATAMART.dbo.[New_BalSheet_Fact] a
inner join [dbo].[Buss_Area_Dim_V] b
on
a.Bus_Area_ID = b.Bus_Area_ID and b.[GBU External Segment Description]= \'Printing\'
inner join [dbo].[BSR_Header_GA_Dim_V] c
on
a.BSR_HEADER_GA_KEY= c.BSR_HEADER_GA_KEY and c.[Group Account Identifier] IN (1291,2150,2151,2152,2153,2154)
inner join [dbo].[Legal_Company_Dim_V] d
on a.Legal_Cmp_Key = d.Legal_Cmp_Key
inner join dbo.Date_Dim dt
on a.Date_key = dt.Date_key and dt.Max_month_Flag = 1
group by d.region,
dt.Qtr_ID
,d.Country
) a
Group BY
a.region
,a.Country
,a.Qtr_ID')
Hope this helps.
Overall, your main issue involves confusing and conflating identifiers and literals. As information, in ANSI-SQL (the formal, industry standard of the SQL language that most RDBMS's adhere to including SQL Server, Oracle, Postgres, etc.), single quotes and double quotes are used for different purposes.
Single quotes are used to enclose string literals within char, varchar, text data type columns such as 'Printing'. Your first error message actually points to Printing as the MSSQL engine attempted to search for a column name since you wrapped this value in double quotes.
Double quotes are used for identifiers including column names and table names such as c."Group Account Identifier". Your second error points to the use of qualifying a table alias, c, to a literal value since you wrapped this value in single quotes.
Below are few common uses of this type:
Double quotes explicitly impose case sensitivity. Specifically, when you wrap column names in double quotes, the same characters in camel case, lower case, and upper case render different values and an error will raise if they do not align to the actual case used in table creation (i.e., tbl."ColumnName" <> tbl."COLUMNNAME").
Double quotes help escape special characters (!##$%^&*?) and spaces. Hence, you can use c."Group Account Identifier" to identify the column. However, some RDBMS's have their own escaping symbols for special characters and spaces which are not ANSI standards. For example, SQL Server can use square brackets [...]; MySQL can use backticks `...`; SQLite and MS Access can use both.
Double quotes help escape reserved words of the current RDBMS which for you includes SQL Server's list. However, it is advised not to use such words, special characters, accents, or spaces in column names.
With that said, like any rule there are exceptions. Both types of quotes may be used with string literals for some databases that allow non-ANSI modes. However, this is not advised to do in practice. Unlike most programming languages such as R, Python, PHP, Perl, XSLT that can swap these two types of quotes for string values, SQL at its base core is not one of them.
Therefore, use either quote type accordingly:
'Printing' AS "External_Segment",
...
AND b."GBU External Segment Description" = 'Printing'
...
AND c."Group Account Identifier" IN (1291, 2150, 2151, 2152, 2153, 2154)
Or
'Printing' AS [External_Segment],
...
AND b.[GBU External Segment Description] = 'Printing'
...
AND c.[Group Account Identifier] IN (1291, 2150, 2151, 2152, 2153, 2154)

Accessing a column named Cast in Bigquery

I have a table and one of the columns is named CAST. How can I access this column. I've tried
Select [Cast] AS cast_s FROM tablename without success, Can I use this name or must I reimport all my data into bigquery?
I know that cast is a function. This is the error message:
Error:
Encountered " "CAST" "Cast "" at line 10, column 63. Was expecting: < E O F > (EOF has no spaces, markdown makes it disappear)
Thanks.
The lexical rules for BQ use backticks for this purpose:
select `cast` as cast_s
from tablename;
The documentation is here.
For BigQuery Legacy SQL you CAN use square brackets
SELECT [cast] as cast_s
FROM tablename
From documentation
You can use square brackets to escape reserved words so that you can
use them as field name and aliases. For example, if you have a column
named "prefix", which is a reserved word in BigQuery syntax, the
queries referencing that field will fail with obscure error messages
unless you escape it with square brackets:
SELECT [prefix] FROM ...

How to use regex replace in Postgres function?

I have postgres function in which i am appending values in query such that i have,
DECLARE
clause text = '';
after appending i have some thing like,
clause = "and name='john' and age='24' and location ='New York';"
I append above in where clause of the query i already have. While executing query i am getting "and" just after "where" result in error
How to use regex_replace so that i remove the first "and" from clause before appending it to the query ?
Instead of fixing clause after the fact, you could avoid the problem by using
concat_ws (concatenate with separator):
clause = concat_ws(' and ', "name='john'", "age='24'", "location ='New York'")
will make clause equal to
"name='john' and age='24' and location ='New York'"
This can be even simpler. Use right() with a negative offset.
Truncates the first n characters and you don't need to specify the length of the string. Faster, simpler.
Double quotes (") are for identifiers in Postgres (and standard SQL) and incorrect in your example. Enclose string literals in single quotes (') and escape single quotes within - or use dollar quoting:
Insert text with single quotes in PostgreSQL
Since this is a plpgsql assignment, use the proper assignment operator :=. The SQL assignment operator = is tolerated, too, but can lead to ambiguity in corner cases.
Finally, you can assign a variable in plpgsql at declaration time. Assignments in plpgsql are still cheap but more expensive than in other programming languages.
DECLARE
clause text := right($$and name='john' and age='24' ... $$, -5)
All that said, it seems like you are trying to work with dynamic SQL and starting off on the wrong foot here. If those values can change, rather supply them as values with the USING clause of EXECUTE and be wary of SQL injection. Read some of the related questions and answers on the matter:
https://stackoverflow.com/search?q=[plpgsql]+[dynamic-sql]+EXECUTE+USING
You do not need regex:
clause = substr(clause, 5, 10000);
clause = substr(clause, 5, length(clause)- 4); -- version for formalists
concat_ws sounds like the best option, but as a general solution for things like this (or any sort of list with a delimiter) you can use logic like (pseudocode):
delim = '';
while (more appendages)
clause = delim + nextAppendage;
delim = ' AND ';
If you want to do it with regular expression try this:
result = regexp_replace(clause, '^and ', '')

insert string with " ' " to oracle

Hey I'm using oracle DB with Iron Python and I'm having trouble with strings that contains the char " ' " like in Mc'donalds. (I know it is looking for the closing ' )
The string is accepted from the user input and I want to add it to my DB as it is, meaning without omitting or changing any character.
How can I do it?
Try using the "q" (quote) function:
INSERT INTO restaurantTable (name)
VALUES (q'[O'Reilly and Conway's Irish Pub]');
You can also double-up the single apostrophes (O''Reilly and Conway''s Irish Pub). But in your case you'd have to parse them out, so either using the quote function or query parameters would work the best.
For more information: Q-quote operator introduced in Oracle 10g
Taken from PL/SQL, how to escape single quote in a string?
You can do it either using Q quoting like
q'[insert into MY_TBL (Col) values('ER0002')]';
OR you can use two quotes to denote a single quote
'insert into MY_TBL (Col) values(''ER0002'')';

how to use a string that contain ' in SQL "IN" clause

i have a string value like 'Apple's'. i want to use this string in SQL "IN" clause like below query
select * from tbl_fruit where nm_fruit IN(''Apple's'','Orange');
how i can get the above query work correctly ?
Many Thanks,
Awais Afzal.
double the single quotes,
select * from tbl_fruit where nm_fruit IN ('Apple''s', 'Orange')
but if you do it on the application level, make sure you parameterized the query :)
I have found SQL correctly interprets the ASCII single-closed-quote (ALT 0146) as an apostrophe in searches while the "IN" treats it like any other character. Now I can search for 'Matt's Macintosh' using Matt(ASCII character 0146)s Macintosh" without messing up my list or the search.