PostgreSQL Concat 2 numbers gives me error - sql

I'm trying to concat 2 numbers from two different columns, those are chain_code and shop_code.
I tried this:
SELECT CONCAT(`shop_code`, `shop_code`) AS myid FROM {table}
But I get an error:
ERROR: operator does not exist: ` integer
LINE 1: SELECT CONCAT(`shop_code`, `shop_code`) AS myid FROM...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
I even tried to convert it to string but couldn't ... CONCAT(to_char(chain_code, '999')...) ... but it says there is no such a function called 'to_sting' (found on PostgreSQL Documentation)

First: do not use those dreaded backticks ` , that's invalid (standard) SQL.
To quote an identifier use double quotes: "shop_code", not `shop_code`
But as those identifiers don't need any quoting, just leave them out completely. In general you should avoid using quoted identifiers. They cause much more trouble than they are worth it.
For details on specifying SQL identifiers see the manual: http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
But concat() only works on text/varchar values, so you first need to convert/cast the integer values to varchar:
SELECT CONCAT(chain_code::text, shop_code::text) AS myid FROM...
but it says there is no such a function called 'to_sting'
Well, the function is to_char(), not to_sting().
Using to_char() is an alternative to the cast operator ::text but is a bit more complicated in this case:
SELECT CONCAT(to_char(chain_code,'999999'), to_char(shop_code, '999999')) AS myid FROM...
The problem with to_string() in this context is, that you need to specify a format mask that can deal with all possible values in that column. Using the cast operator is easier and just as good.
Update (thanks mu)
As mu is to short pointed out, concat doesn't actually need any cast or conversion:
SELECT CONCAT(chain_code, shop_code) AS myid FROM...
will work just fine.
Here is an SQLFiddle showing all possible solutions: http://sqlfiddle.com/#!15/2ab82/3

Related

Operator does not exist date=integer when filtering for dates in postgreSQL

I have a large data set on dbeaver (postgreSQL), and I am trying to filter for the following:
select * from raw_data_file where data_file_group_id = 2592 and dl_date = 2022-06-15
However, I am getting an error for the dl_date part of the filter- any suggestions?
SQL Error [42883]: ERROR: operator does not exist: date = integer¶ Hint: No operator matches the given name and argument types. You might need to add explicit type casts.¶ Position: 74
Stu's comment is correct. Use quotes, single quotes, otherwise the subexpression looks like a couple of subtractions.

SQL overlap statement

I'm trying to do overlap in SQL (using postgres) but receive an syntax error. And i do not know why I'm getting error and whats wrong with my SQL Statement
Error text
[42601] ERROR: syntax error at or near "[" Position: 296
SQL Statement
SELECT *,
ARRAY_AGG("reserve"."state_id" ) AS "states" FROM "orders_order"
JOIN "reserve" ON ("order"."id" = "reserve"."order_id")
GROUP BY "order"."id"
HAVING (NOT (ARRAY_AGG("reserve"."state_id" )&& ['test']::varchar(255)[]))
As documented in the manual there are two ways to specify an array:
First with the array keyword:
array['test']
or as a string enclosed with curly braces:
'{test}'::text[]
In the second case the casting might or might not be needed depending on the context on where it's used.
There is no need to cast it to a varchar(255)[] array. text[] will do just fine - especially when comparing it to the result of an array_agg() which returns text[] as well.

how to use substr in SQL Server?

I have the following extract of a code used in SAS and wanted to write it in SQL Server to extract data.
substr(zipname,1,4) in("2000","9000","3000","1000");run;
How do I write this in SQL Server ?
I tried and got this error:
An expression of non-boolean type specified in a context where a
condition is expected
In sql server, there's no substr function (it's substring)
by the way, you need a complete query...
select blabla
from blibli
where substring(zipname, 1, 4) in ('2000', '9000', 3000', '1000')
assuming zipname is a varchar or something like that...
You need a table that you are getting the records from, and zipname would be a column in the table. The statement would be something like this:
select * from tablename where substring(zipname,1,4) in ('2000','9000','3000','1000')
Since you want the first x characters, you can also use the left() function.
where left(zipname, 4) in (values go here)
Bear in mind that your values have to be single quoted. Your question has double quotes.

Converting char to integer in INSERT using IIF and SIMILAR TO

I am using in insert statement to convert BDE table (source) to a Firebird table (destination) using IB Datapump. So the INSERT statement is fed by source table values via parameters. One of the source field parameters is alphanum (SOURCECHAR10 char(10), holds mostly integers and needs to be converted to integer in the (integer type) destination column NEWINTFLD. If SOURCECHAR10 is not numeric, I want to assign 0 to NEWINTFLD.
I use IIF and SIMILAR to to test whether the string is numeric, and assign 0 if not numeric as follows:
INSERT INTO "DEST_TABLE" (......, "NEWINTFLD",.....)
VALUES(..., IIF( :"SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*', :"SOURCECHAR10", 0),..)
For every non numeric string however, I still get conversion errors (DSQL error code = -303).
I tested with only constants in the IIF result fields like SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*', 1, 0) and that works fine so somehow the :SOURCECHAR10 in the true result field of the IIF generates the error.
Any ideas how to get around this?
When your query is executed, the parser will notice that second use of :"SOURCECHAR10" is used in a place where an integer is expected. Therefor it will always convert the contents of :SOURCECHAR10 into an integer for that position, even though it is not used if the string is non-integer.
In reality Firebird does not use :"SOURCECHAR10" as parameters, but your connection library will convert it to two separate parameter placeholders ? and the type of the second placeholder will be INTEGER. So the conversion happens before the actual query is executed.
The solution is probably (I didn't test it, might contain syntax errors) to use something like (NOTE: see second example for correct solution):
CASE
WHEN :"SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*'
THEN CAST(:"SOURCECHAR10" AS INTEGER)
ELSE 0
END
This doesn't work as this is interpreted as a cast of the parameter itself, see CAST() item 'Casting input fields'
If this does not work, you could also attempt to add an explicit cast to VARCHAR around :"SOURCECHAR10" to make sure the parameter is correctly identified as being VARCHAR:
CASE
WHEN :"SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*'
THEN CAST(CAST(:"SOURCECHAR10" AS VARCHAR(10) AS INTEGER)
ELSE 0
END
Here the inner cast is applied to the parameter itself, the outer cast is applied when the CASE expression is evaluated to true

Does this behavior exist in all major databases?

mysql> select 0.121='0.121';
+---------------+
| 0.121='0.121' |
+---------------+
| 1 |
+---------------+
Does it hold for other database that number='number' is true?
First of all: most databases are using localized number formats. So turning a number into a string will most probably not always be the same as your hard-coded string.
Then: you will get problems with the sql syntax you use. See my experiments with oracle bellow.
In Oracle you always need a FROM clause (except they changed this in version 10).
select 0.121='0.121' from sys.dual
In Oracle, you can't have an expression like this in the select clause.
You need a case statement:
select case when 0.121 = '0.121' then 1 else 0 end as xy
from sys.dual
Then you get an error that it is no number. To fix this, convert it:
select case when To_Char(0.121) = '0.121' then 1 else 0 end as xy
from sys.dual
this will return 0! Because, on my machine, 0.121 is converted to the string ".121". These are Swiss settings. If I had German settings, it would be ",121" (note the comma).
So to finally answer the question: No.
Even if it does. What does this help you ?
I would never, ever, make this assumption anyway. You always need to convert both operands to the same type so that, at least, you know what you are comparing.
Most of the reputable databases will do an implicit conversion for this type of query. There may be published rules for implicit conversions on a particular system - you'd have to look at the vendor coumentation to find out what implicit conversions are done on your system.
For instance,
here's an official reference from Microsoft for SQL Server 2000, and
here's a blog entry on SQL Server implicit conversions.
No.
I don't know why Stackoverflow requires me to enter more than 3 characters in answer to this question.
Postgresql is a little more strict than mysql about type conversion, and does not let you implicitly cast/convert between numbers and strings. This is sane behaviour, and it is getting slightly more strict with newer versions. Some examples, from Postgres 8.4:
db=# select 0.112::float = '0.112'::text;
ERROR: operator does not exist: double precision = text
LINE 1: select 0.112::float = '0.112'::text;
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
db=# select 0.112 = ('0.1' || '12');
ERROR: operator does not exist: numeric = text
LINE 1: select 0.112 = ('0.1' || '12');
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
db=# select 0.112 = ('0.1' || '12')::float; -- explicit cast
t
However, this example (the original question) works:
db=# select 0.122 = '0.122';
t
This is a little surprising (or misleading), given the above. But it has to do with how the query is parsed: when it sees an (unqualified) '0.122' literal, the parser does not necessarily assumes it is of TEXT type, but assigns instead a preliminary "unknown" type; its final type is deduced later by some heuristics.
Anyway, it's bad practice to rely on this, as mentioned by others.