What does :: do in PostgreSQL? [duplicate] - postgresql

This question already has answers here:
Double colon `::` notation in SQL
(4 answers)
Closed 9 years ago.
I have seen :: in variety of places involving postgres code I have seen on the net. For example:
SELECT '{apple,cherry apple, avocado}'::text[];
It seems to be some sort of cast. What exactly is :: in postgres and when should it be used?
I tried a bit of googling and searched the Postgres docs for :: but got no good results.
I tried following searches in Google:
postgres double colon
postgres ::
::
I tried the following searches in the postgres docs search button
double colon
double colon cast
::
This was almost embarrassing to ask on SO, but I figured Google will hopefully see this answer for other people in the future.

A type cast specifies a conversion from one data type to another.
PostgreSQL accepts two equivalent syntaxes for type casts, the PostgreSQL-specific value::type and the SQL-standard CAST(value AS type).
In this specific case, '{apple,cherry apple, avocado}'::text[]; takes the string literal {apple,cherry apple, avocado} and tells PostgreSQL to interpret it as an array of text.
See the documentation on SQL expressions and arrays for details.

What #PSR and #Craig wrote.
Plus, there are two more syntax variants:
1. type value
This form only casts constants (string literals). Like in:
SELECT date '2013-03-21';
More in the manual in the chapter Constants of Other Types.
2. type(value)
That's the function-like syntax. Works only for types whose names are valid as function names. Like in:
SELECT date(date_as_text_col) FROM tbl;
More in the manual in the chapter Type Casts.
More comprehensive answer:
Postgres data type cast

Related

Complex RegEx in T-SQL

I recently started using RegEx as conditional in my queries, but it seems that T-SQL has limited support for the official syntax.
As an example, I wish to test if a string is valid as a time between 00:00 and 23:59, and a fine RegEx expression would be "([0-1][0-9]|[2][0-3]):([0-5][0-9])":
select iif('16:06' like '([0-1][0-9]|[2][0-3]):([0-5][0-9])', 'Valid', 'Invalid')
.. fails and outputs "Invalid". Am I right to understand that T-SQL cannot handle groupings and conditionals (|)? I wound up lazily using a simplified RegEx which does not properly test the string - which I am fairly unhappy with:
select iif('16:06' like '[0-2][0-9]:[0-5][0-9]', 'Valid, 'Invalid')
.. which returns "Valid", but would also consider the string "28:06" as valid.
I know I can add further checks to fully check if it is a valid time string, but I would much prefer to take full advantage of RegEx.
Simply asked: Am I just doing or thinking things wrong about this being a limitation, and if yes - how can I use proper RegEx in T-SQL?
The pattern syntax used for LIKE and PATINDEX is much more limited than what's commonly known as Regular Expressions.
In standard SQL it actually has only 2 special characters.
% : wildcard for 0 or more characters
_ : any 1 character
And T-SQL added the character class [...] to the syntax.
But to test if a string contains a time, using LIKE is a clumsy way to do it.
In MS Sql Server one can use the TRY_CONVERT or TRY_CAST functions.
They'll return NULL is the conversion to a datatype fails.
select IIF(TRY_CAST('16:06' AS TIME) IS NOT NULL, 'Valid', 'Invalid')
This will return 'Valid' for '23:59', but 'Invalid' for '24:00'
You may use the following logic:
SELECT IIF('16:06' LIKE '[01][0-9]:[0-5][0-9]' OR
'16:06' LIKE '2[0-3]:[0-5][0-9]', 'Valid', 'Invalid');
The first LIKE expression matches 00:00 to 19:59, and the second LIKE matches 20:00 to 23:59. If SQL Server supported full regex, we could just use a single regex expression with an alternation.
I would recommend writing a user defined function using SQLCLR. Since .Net supports Regex you can port it to T-SQL. First link in Google gave this implementation, but there may be other (better) implementations.
Caveat - use of SQLCLR requires elevated permissions and may lead to security issues or performance issues or even issues with stability of the SQL Server if not implemented correctly. But if you know what you are doing this may lead to significant enhancements of T-SQL specific for your use cases.

Difference between STRPOS and POSITION in postgresql

Beginner here.
Is there any other difference apart from syntax in position and strpos function?
If not then why do we have two functions which can achieve the same thing just with a bit of syntax difference?
Those functions do the exactly same thing and differ only in syntax. Documentation for strpos() says:
Location of specified substring (same as position(substring in string), but note the
reversed argument order)
Reason why they both exist and differ only in syntax is that POSITION(str1 IN str2) is defined by ANSI SQL standard. If PostgreSQL had only strpos() it wouldn't be able to run ANSI SQL queries and scripts.
You can use both commands in order to reach the same goal, i.e. finding the location of a substring in a given string. However, they have different syntaxes and order of arguments:
strpos(String, Substring);
position(Substring in String);
Take a look at all string functions and operators of PostgreSQL here

"sqlLike" and "sqlLikeCaseInsensitive" escape character?

Is there any way to escape SQL Like string when using "sqlLike" and "sqlLikeCaseInsensitive"?
Example: I want a match for "abc_123". Using "_______" (7 underscores) would also return "abcX123", how can I enforce "_" as the 4th character?
If you issue the query in persistence, this is actually not a mdriven issue but an SQL issue as mdriven converts the Expression into SQL. So if you really want to restrict the results to underscores only take a look to this question:
Why does using an Underscore character in a LIKE filter give me all the results?
The way to escape the underscore may depend on the needs of your SQL database as the different answers indicate.

Does the string functions in DB2 work on a limited ASCII character set?

In a program I have used a function RPAD() to format data coming from DB2 db.
In one instance the value was Ãmber. The following function:
RPAD('Ãmber',10,' ')
gives 9 characters only.
The ASCII value of 'Ã' is 195. I am not able to understand the reason for this behaviour.
Could someone share their experience.
Thanks
By default, DB2 will consider the length of à to be 2, likely because it is counting bytes rather than characters.
values(LENGTH('Ãmber'))
6
You can override it for LENGTH and many other functions
values(LENGTH('Ãmber', CODEUNITS16))
5
Unfortunately, RPAD does not take a parameter like this. I'm guessing this might be because the function was added for Oracle compatibility rather than on its own merits.
You could write your own RPAD function as a stored procedure or UDF, or just handle it with a CASE statement if this is the only place where you need it.

Possible to use named placeholders in DBI's selectcol_arrayref & Co.?

Is it somehow possible to use named placeholders where DBI allows #bind_values? E. g., I would like to make statements like:
my $s = $DB->selectcol_arrayref ("SELECT a FROM b
WHERE c = ? OR d = ? OR e = ?;",
{},
$par1, $par2, $par1) or
die ($DB->errstr ());
less prone to mistakes. I'm using DBD::Pg and DBD::SQLite.
What sorts of placeholders (if any) are supported depends on the driver:
Placeholders and Bind Values
Some drivers support placeholders and bind values.
[...]
Some drivers also allow placeholders like :name and :N (e.g., :1, :2, and so on) in addition to ?, but their use is not portable.
But you're in luck, the PostgreSQL driver supports named or numbered parameters:
There are three types of placeholders that can be used in DBD::Pg. The first is the "question mark" type, in which each placeholder is represented by a single question mark character.
[...]
The method second type of placeholder is "dollar sign numbers".
[...]
The final placeholder type is "named parameters" in the format ":foo".
And the SQLite driver also supports them:
SQLite supports several placeholder expressions, including ? and :AAAA.
The downside is that you'll end up using bind_param a lot with the named parameters so you won't be able to use conveniences like selectcol_arrayref and $sth->execute(1,2,3) (Note: If anyone knows how to use named placeholders with execute I'd appreciate some pointers in a comment, I've never figured out how to do it). However, you can use the various forms of number placeholders (such as select c from t where x = $1 for PostgreSQL or select c from t where x = ?1 for SQLite).
Also be aware that PostgreSQL uses colons for array slices and question marks for some operators so sometimes the standard ? placeholders and :name named placeholders can cause problems. I've never had any problems with ? but I've never used the geometric operators either; I suspect that sensible use of whitespace would avoid any problems with ?. If you're not using PostgreSQL arrays, then you probably don't have to worry about array slices fighting with your :name named placeholders.
Executive Summary: You can't use named placeholders with selectcol_arrayref or similar methods that work with #bind_params. However, with SQLite and Postgresql, you can use numbered placeholders ($1, $2, ... for Postgresql or ?1, ?2, ... for SQLite) with the methods that work with #bind_params or you can use named placeholders (:name for both PostgreSQL and SQLite) if you're happy using the longer prepare/bind_param/execute/fetch sequence of methods and you'll have to be careful if you use PostgreSQL arrays in your queries.