Postgres COLLATION FOR - sql

I have tried the function collation for(argument) which is described in the PostgreSQL documentation. But when I try to execute the query which is given in the same PostgreSQL documentation, I get an error. Actually, the statement that I ran was
SELECT collation for ('sample') FROM pg_description LIMIT 1;
It could be better if someone gives the exact correct query and the correct parameters for the function.
What is the use case of this function?
If the function name was wrong, please give me the correct function name.

Strictly speaking, COLLATION FOR is not a "function", but a syntax element of SQL. The underlying function in Postgres is pg_collation_for().
All required information is in the manual, even for your outdated version Postgres 9.5. Search for "collation for" on that manual page and you'll find an example with explanation.
But it's more clearly documented in the current version (quote from pg 15):
Returns the name of the collation of the value that is passed to it.
The value is quoted and schema-qualified if necessary. If no collation
was derived for the argument expression, then NULL is returned. If
the argument is not of a collatable data type, then an error is
raised.
Bold emphasis mine.
Basically, only string types like text and varchar are collatable.
No error should happen for the example query from the manual as pg_description.description is type text. But you ran a different one:
SELECT collation for ('sample') FROM pg_description LIMIT 1;
Which can be shortened to just:
SELECT collation for ('sample');
'sample' is an untyped string literal, i.e. type "unknonwn", but it will be coerced to text by default, so it should not error out, either.

Related

regexp_like that mirrors contains near

I'm trying to speed up a query that uses Contains Near with one that uses regexp_like. The initial Contains Near query takes about 45 minutes to run. Clob Column holds large "documents" and is domain indexed.
Initial query:
SELECT column1
FROM TEST
WHERE CONTAINS(column1,'{NEAR(quick,fox, lazy), 3, FALSE}')>0;
Proposed query:
SELECT column1
FROM TEST
WHERE REGEXP_LIKE(column1, '(\b(quick|fox|lazy)(?:\W+\w+){1,6}?\W(quick|fox|lazy)(?:\W+\w+){1,}?\W(quick|fox|lazy)\b)','i')
I got the original regexp syntax from here:
https://www.regular-expressions.info/near.html.
Problem:
I get the regexp code to work in html https://www.regextester.com, but when I put it in Oracle it doesn't find anything. What is wrong with my syntax? I can't figure it out. Does Oracle handle REGEXP differently?
Alex, you were exactly right. I don't see how to select your answer as correct though.
My problem was apparently that I was using regexp parameters that Oracle doesn't recognize. So, whereas it worked on https://www.regextester.com, it failed to work in Oracle because most of what I used isn't recognized as usable with regexp in Oracle. I really think Oracle should expand their regexp codes it recognized. This was really frustrating.

Simple SELECT statement fails with "syntax to use near", "ORA-00906", "syntax error at or near" or "syntax near the keyword"

I have a very simple SQL statement
SELECT * FROM Table;
but, my query engine returns a syntax error. Why?
Error Details:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in >System.Data.dll
Additional information: Incorrect syntax near the keyword 'Table'.
How is this possible? I checked the connection string and it is correct.
I checked my table name and it is also correct.
What I am doing wrong?
Okay, Table is a reserved keyword in all variants of SQL.
If you want to call a table Table, and use it in a statement, you have to tell your sql engine that it is an identifier. To do this you need to use Identifier Qualifiers.
for (MS SQL Server) TSQL use square brackets
SELECT * FROM [Table];
for MySQL use `
SELECT * FROM `Table`;
for Oracle and PostgreSQL use quotation marks,
these are standards compliant.
SELECT * FROM "Table";
for SQLite you can use any of the above, but quotation marks are prefered.
The Identifier Qualifiers tell the engine that this is an identifier (the name of an object.) Not the name of a keyword, even if they happen to be the same. Without your guidance the query engine can get confused and report an error, or worse, do something unexpected.
Using Identifier Qualifiers is good practice, even if the identifers are not keywords.
They better define statements for all parsers, including the fleshy kind.
Naming objects after keywords is generally considered bad practice. So you should try to avoid making identifers the same as keywords. The occasions when a reserved keyword is descriptive of the contents of a table are rare, see the footnote.
e.g. your table is not a Table of tables.
The problem and advice is not limited to Tables, Identifiers are required for all database objects inluding Schema, Views and the many types that exist, standard and vendor-specific.
Another form of good practice is to prefix Table indentifiers with a Schema identifier, this helps the query engine a little.
When including the Schema identifier, the identifer should be qualified,
for (MS SQL Server) TSQL use square brackets
SELECT * FROM [dbo].[Table];
for MySQL use `
SELECT * FROM `dbo`.`Table`;
for Oracle, PostgreSQL and SQLite use quotation marks
SELECT * FROM "dbo"."Table";
even if your Schema is not named after a keyword, as should be the case.
For your reference, to help you avoid conflicts.
A list of TSQL Reserverd Keywords.
A list of MySQl Reserved Keywords.
A list of Oracle Reserved Keywords.
A list of SQLite Reserved Keywords.
A list of PostgreSQL Reserved Keywords.
Notable "gotcha's" include USER and ERROR, which seem to come up when designing systems.
Footnote:
There are occasions when using reseved words for object names may be semantically correct.
Consider the contrived example of an information system for a furniture shop. In this scenario, a table of tables (kitchen, garden, dining, apothecary etc.) may be correct. So, you could argue Table was the correct identifier.
If you always use Identifier Qualifiers, you won't get burned.
If you are using SQL server you need to wrap table in brackets [] as table is keyword in SQL Server
SELECT * FROM [Table]

what is the difference between SUBSTRING and SUBSTR functions (SQL)?

before I used :
entityManagerFactory.createQuery("select p FROM Pays p where SUBSTRING(p.libeleClient, 0,1)
but when I use this query :
entityManagerFactory.createQuery("select p FROM Pays p where SUBSTR(p.libeleClient, 0,1)
I get an exception :(
who to remplace SUBSTRING by SUBSTR ?
SUBSTR is the function from Oracle
SUBSTRING is the function from MySql
depends on DB which u r using
EDIT:
try to edit your java code like below
String query = "select p FROM Pays p where SUBSTRING(p.libeleClient, 0,1)";
// from Connection Object (connection)
DatabaseMetaData meta = connection.getMetaData();
//If the DB is Oracle
if(meta.getDatabaseProductName()).contains("Oracle")) {
entityManagerFactory.createQuery(query.replace("SUBSTRING", "SUBSTR"));
}// If the DB not Oracle , any Other like MySql
else {
entityManagerFactory.createQuery(query);
}
substring is the sql operation defined in the sql standard ISE:IEC 9075:1992.
substr is an old syntax used by oracle. This wrong syntax is completely inconsistent with sql usage of real english words, never abbreviations.
Oracle still does not support the standard syntax.
Did anyone wrote a hack in oracle to support the standard syntax ?
You don't say what exception you get, but I 'm guessing it's a syntax error. The correct syntax for Oracle's SUBSTR() is ...
where SUBSTR(p.libeleClient, 0,1) = 'X'
...(or whatever). That is the first occurence of a single character must equal; some specified value. SUBSTR() is not a boolean function.
Whereas SUBSTRING() is not an oracle function at all. Either you've borrowed the syntax from some other database, or you're using a bespoke function without realising it.
"I tried your suggestion but it does not work"
Do you get an error? Or do you mean it doesn't return any records? Because I have given a perfectly valid usage, as defined in the documentation. But you haven't given any examples of your data, so it's almost impossible for me to provide a solution which will return rows from your database.

performance of parameterised SQL

I have a query like
SELECT *
FROM myTable
WHERE key LIKE 'XYZ'
The value 'XYZ' is entered by users (and may include % and _)
If I construct the query using string concatenation it runs in 10 seconds.
But this is unsafe, and I should use a parameterised query.
So I'm constructing the query using the odbc command object and it's execute method, and passing a parameter.
SELECT *
FROM myTable
WHERE key LIKE ?
Unfortunately the parameterised SQL execute method takes a full minute.
This query is one of many that are part of a drill-down / investigation package, and I've had similar slow downs with all the parameterised queries (compared to string concatenation).
How do I find out where the time is going (and fix it) ?
Here's my guess without further information.
I've had similar problems on SQL Server. In SQL Server when the column on your table is 'varchar' and the parameterised query parameter is 'nvarchar' (or vice versa), this causes SQL Server to ignore an available index because the parameter type doesn't match the index type, which in turn results in a table scan.
It's possible the same thing happens for Sybase. If you can see the generated query you can confirm if there's a type mismatch.
If this is the case, then two solutions would be
explicitly set the type of the parameter to match the column type
change the type of the column to match the parameter type being generated
Mitch had the right suggestion.
I had to change the connection string to use the OLEDB driver, then I could set the options:
Optimize Prepare=None
Select Method=Direct

Can you explain this SQL injection?

The website i worked was recently attempted to be hacked by the following SQL injection script
boys' and 3=8 union
select 1,
concat(0x232425,ifnull(`table_name`,0x30),char(9),ifnull(`table_rows`,0x30), char(9),0x252423),
3,4,5,6,7,8,9
from `information_schema`.`tables`
where table_schema=0x62646B3032 limit 44,1 -- And '8'='8
This injection returned the mysql table name. This was reported by the error reporting system on that website and we managed to fix that part however I am not able to understand what does the above injection mean?
Anyone can explain this?
Penuel
They're using a select from the Information Schema views in mysql server :
http://dev.mysql.com/doc/refman/5.0/en/information-schema.html
They use some clever hacks to rout out simple sql injection prevention techniques.
According to this the MySQL concat()
Returns the string that results from
concatenating the arguments. May have
one or more arguments. If all
arguments are nonbinary strings, the
result is a nonbinary string. If the
arguments include any binary strings,
the result is a binary string. A
numeric argument is converted to its
equivalent binary string form
So 0x232425 is converted to #$% which is simply added to the begining and end of the table_name field. Maybe just to make it easier for them to pull out the Table names later using Regex.
Later on the char(9) is equivalent to a tab as you can see here and is just there to format the output nicer.
The 3,4,5,6,7,8,9 is just there so that the columns match the boys table that they are performing the Union on.
This injection returned the mysql table name.
Do you mean that your website displayed the table name when you gave it this input, or that the query returns that when run from the mysql client? If it showed on your website, then the attacker has the ability to inject much more harmful queries. Check your data.