Non-integer constants in the ORDER BY clause - sql

Upgrade advisor says:
Non-integer constants are not allowed in the ORDER BY clause in 90 or later compatibility mode".
But, when I try the below statement in SQL Server 2008, it works just fine. So, my questions is: What exactly is a non-integer constant?
SELECT
COALESCE( fi.Payee, -1 ) AS 'Payee',
COALESCE( p.ProvNo, '' ) AS 'ProviderNo'
FROM
dbo.tbl_Emp
ORDER BY
'Payee',
'ProviderNo'

Integer constants are represented by a string of numbers that are not enclosed in quotation marks and do not contain decimal points. integer constants must be whole numbers; they cannot contain decimals.
The following are examples of Integer constants:
1894
2
You have mentioned Non-Integer Constants in '' double quotes in your Query
Refer this MSDN link for Constants

Got the same problem in a Spring Boot context. I created a native query for a Postgres database with jpa.
This query produces an non-integer constant in ORDER BY exception.
#Query(nativeQuery = true, value = "SELECT * FROM farm.cow o WHERE o.id > :uuid ORDER BY 'id' FETCH FIRST :limit ROWS ONLY ")
List<Cow> findCows(#Param("uuid") UUID String, #Param("limit") int limit);
To solve this exception I just change the ORDER BY 'id' to -> ORDER BY \"id\" . This approach fixed my problem.
#Query(nativeQuery = true, value = "SELECT * FROM farm.cow o WHERE o.id > :uuid ORDER BY \"id\" FETCH FIRST :limit ROWS ONLY ")
List<Cow> findCows(#Param("uuid") UUID String, #Param("limit") int limit);

Related

Excel SQL data type mismatch

I have this query
SELECT *
FROM [RawData$]
WHERE 'Temperature[°C]' <= 100
But at the execution I get this error:
Data type mismatch in criteria expression.
The data in this column is 100% integer so I guess there is no problem.
Further this works fine:
SELECT *
FROM [RawData$]
WHERE 'Temperature[°C]'
I also tried this too but then I get no values at all:
SELECT *
FROM [RawData$]
WHERE 'Temperature[°C]' <= '100'
Actually the final question would be:
What query do i need to search a column which name is: Temperature[°C]
[Temperature[°C]][Temperature[[]°C]]
do not work.
This WHERE 'Temperature[°C]' <= 100 compares the literal string Temperature[°C] to the Integer 100.
Use WHERE [Temperature(°C)] < 100 instead.
Note:
square brackets [] are reserved to be wrapped around fieldnames (much like you tried to use single quotes ')
in this particular case, the square brackets in your header get interpreted as normal brackets ().
I think the issue is the column name has square brackets, so you have to maybe do it like this:
SELECT *
FROM [RawData$]
WHERE "Temperature[°C]" <= '100'
With the double quotes, instead. Let me know if that works.

How to check if a value is a number in SQLite

I have a column that contains numbers and other string values (like "?", "???", etc.)
Is it possible to add an "is number" condition to the where clause in SQLite? Something like:
select * from mytable where isnumber(mycolumn)
From the documentation,
The typeof(X) function returns a string that indicates the datatype of the expression X: "null", "integer", "real", "text", or "blob".
You can use where typeof(mycolumn) = "integer"
You could try something like this also:
select * from mytable where printf("%d", field1) = field1;
In case your column is text and contains numeric and string, this might be somewhat helpful in extracting integer data.
Example:
CREATE TABLE mytable (field1 text);
insert into mytable values (1);
insert into mytable values ('a');
select * from mytable where printf("%d", field1) = field1;
field1
----------
1
SELECT *
FROM mytable
WHERE columnNumeric GLOB '*[0-9]*'
select * from mytable where abs(mycolumn) <> 0.0 or mycolumn = '0'
http://sqlfiddle.com/#!5/f1081/2
Based on this answer
To test whether the column contains exclusively an integer with no other alphanumeric characters, use:
NOT myColumn GLOB '*[^0-9]*' AND myColumn LIKE '_%'
I.e., we test whether the column contains anything else than a digit and invert the result. Additionally we test whether it contains at least one character.
Note that GLOB '*[0-9]*' will find digits nested between other characters as well. The function typeof() will return 'text' for a column typed as TEXT, even if the text represents a number. As #rayzinnz mentioned, the abs() function is not reliable as well.
As SQLite and MySQL follow the same syntax and loose datatypes.
The query below is also possible
SELECT
<data>
, (
LENGTH(CAST(<data> AS UNSIGNED))
)
=
CASE WHEN CAST(<data> AS UNSIGNED) = 0
THEN CAST(<data> AS UNSIGNED)
ELSE (LENGTH(<data>)
) END AS is_int;
Note the <data> is BNF you would have the replace those values.
This answer is based on mine other answer
Running SQLite demo
For integer strings, test whether the roundtrip CAST matches the original string:
SELECT * FROM mytable WHERE cast(cast(mycolumn AS INTEGER) AS TEXT) = mycolumn
For consistently-formatted real strings (for example, currency):
SELECT * FROM mytable WHERE printf("%.2f", cast(mycolumn AS REAL)) = mycolumn
Input values:
Can't have leading zeroes
Must format negatives as -number rather than (number).
You can use the result of the function CAST( field as INTEGER) for numbers greater than zero and the simple condition like '0' per numbers equal to zero
SELECT *
FROM tableName
WHERE CAST(fieldName AS INTEGER) > 0
UNION
SELECT *
FROM tableName
WHERE fieldName like '0';
This answer is comprehensive and eliminates the shortcomings of all other answers. The only caveat is that it isn't sql standard... but neither is SQLite. If you manage to break this code please comment below, and I will patch it.
Figured this out accidentally. You can check for equality with the CAST value.
CASE {TEXT_field}
WHEN CAST({TEXT_field} AS INTEGER) THEN 'Integer' -- 'Number'
WHEN CAST({TEXT_field} AS REAL) THEN 'Real' -- 'Number'
ELSE 'Character'
END
OR
CASE
WHEN {TEXT_field} = CAST({TEXT_field} AS INTEGER) THEN 'Integer' --'Number'
WHEN {TEXT_field} = CAST({TEXT_field} AS Real) THEN 'Real' --'Number'
ELSE 'Character'
END
(It's the same thing just different syntax.)
Note the order of execution. REAL must come after INTEGER.
Perhaps their is some implicit casting of values prior to checking for equality so that the right-side is re-CAST to TEXT before comparison to left-side.
Updated for comment: #SimonWillison
I have added a check for 'Real' values
'1 frog' evaluated to 'Character' for me; which is correct
'0' evaluated to 'Integer' for me; which is correct
I am using SQLite version 3.31.1 with python sqlite3 version 2.6.0. The python element should not affect how a query executes.

Fetch column from result set having expression based SELECT without alias name

This should be a Basic Question, but I was unable to answer when asked for. Sorry if it is too broad!
SELECT * FROM
(
SELECT MYGROUPKEY,MAX(MYCOLUMN)/MIN(MYCOLUMN) FROM
MYTABLE
GROUP BY MYGROUPKEY
) MYSUBQUERY;
This Query is Syntactically Valid. But how would someone fetch the second column of this resultset, if they have to attempt with some identifier? (The column was never provided with an alias). How can it be formatted in SQL*Plus. (COL <column_name> FORMAT A<num>)
Will that be first few characters of the text MAX(MYCOLUMN)/MIN(MYCOLUMN).
I understand, RDBMS concept doesnt like this. But still why would the Database execute this SQL then? It never name the resultset's columns unless the query carry it?
Assuming that the expression is less than 30 characters
SQL> column "MAX(MYCOLUMN)/MIN(MYCOLUMN)" format <<some format>>
should work. You can realistically look at the raw column header in SQL*Plus (before applying any formatting) to see what the assigned alias is. Depending on the actual expression, there can be various rules applied-- eliminating spaces, for example, and limiting the expression to 30 characters. It's generally easier to copy & paste from SQL*Plus and surround the assigned alias with double quotes.
There is an implicit alias which is the expression with any whitespace removed. But as the expression contains characters which aren't invalid for an identifier it has to be quoted, as "MAX(MYCOLUMN)/MIN(MYCOLUMN)". You can refer to that in an SQL*Plus column command too.
e.g.
SELECT MYGROUPKEY, "MAX(MYCOLUMN)/MIN(MYCOLUMN)" FROM
(
SELECT MYGROUPKEY,MAX(MYCOLUMN) / MIN(MYCOLUMN)
FROM MYTABLE
GROUP BY MYGROUPKEY
) MYSUBQUERY;
SQL Fiddle.
There is a further wrinkle though. As identifieres can only be 30 characters, if the expression is longer than that the implicit alias is also too long to be referred to within the SQL itself. This would get an ORA-00972:
SELECT MYGROUPKEY, "MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000)" FROM
(
SELECT MYGROUPKEY,MAX(MYCOLUMN) / MIN(MYCOLUMN) * (1000 / 1000)
FROM MYTABLE
GROUP BY MYGROUPKEY
) MYSUBQUERY;
It's better to add your own aliases, even for shorter expressions.
But you can sometimes still use the longer alias, for example through JDBC, where it appears in the metadata (as it does here as the column label). A section of a test that accesses the same data as the SQL Fiddle:
pStmt = (OraclePreparedStatement) conn.prepareStatement(
"SELECT MYGROUPKEY,MAX(MYCOLUMN) / MIN(MYCOLUMN) * (1000 / 1000) "
+ "FROM MYTABLE GROUP BY MYGROUPKEY");
rSet = (OracleResultSet) pStmt.executeQuery();
OracleResultSetMetaData rsmd = (OracleResultSetMetaData) rSet.getMetaData();
for( int i=1; i <= rsmd.getColumnCount(); i++ ) {
System.out.println( "Column label: " + rsmd.getColumnLabel(i));
System.out.println( "Column Type: " + rsmd.getColumnTypeName(i));
System.out.println();
}
while (rSet.next())
{
System.out.println("MYGROUPKEY: " + rSet.getInt("MYGROUPKEY"));
System.out.println("MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000): "
+ rSet.getInt("MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000)"));
}
Produces output:
Column label: MYGROUPKEY
Column Type: NUMBER
Column label: MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000)
Column Type: NUMBER
MYGROUPKEY: 1
MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000): 2
Note the the column label/name reported n the metadata is the same as shown in the Fiddle, the expression with whitespace removed; and that I can use that as the argument for getInt() even though it's longer than 30 characters.

Constant Expression in Linq to SQL is not correctly compiled

I have two table (mysql) with master-detail relationship that I want to query in Linq (and then experiment it in LinqPad). The problem is Linq to SQL can't produce the correct result nor SQL statement for the following query
from m in masters
select new {
m.Code,
m.Total,
Value = m.details.Sum(d => d.Qty * d.Price * (1 - 6/100))
}
and another one
from m in masters
select new {
m.Code,
m.Total,
Value = m.details.Sum(d => d.Qty * d.Price * 0.94)
}
the first query will not produce the correct result as the latter, the problem after I check in LinqPad lies within the (1 - 6/100) that compiled into 1.0. Can someone explain why?
The first expression uses integer math and thus is correct, just not what you expected. You've assumed that C# will infer floating point semantics from integer literals. The second expression is a simply a double literal.
In integer math, 6/100 is 0, so (1 - 6/100) is 1. You need to coerce the division expression into using double values by making the numerator or denominator a double literal.
Instead try:
Value = m.details.Sum(d => d.Qty * d.Price * (1 - 6/100.0))
Note the .0 to make that a double expression.

PostgreSQL: IN A SINGLE SQL SYNTAX order by numeric value computed from a text column

A column has a string values like "1/200", "3.5" or "6". How can I convert this String to numeric value in single SQL query?
My actual SQL is more complicated, here is a simple example:
SELECT number_value_in_string FROM table
number_value_in_string's format will be one of:
##
#.##
#/###
I need to sort by the numeric value of this column. But of course postgres doesn't agree with me that 1/200 is a proper number.
Seeing your name I cannot but post a simplification of your answer:
SELECT id, number_value_in_string FROM table
ORDER BY CASE WHEN substr(number_value_in_string,1,2) = '1/'
THEN 1/substr(number_value_in_string,3)::numeric
ELSE number_value_in_string::numeric END, id;
Ignoring possible divide by zero.
I would define a stored function to convert the string to a numeric value, more or less like this:
CREATE OR REPLACE FUNCTION fraction_to_number(s CHARACTER VARYING)
RETURN DOUBLE PRECISION AS
BEGIN
RETURN
CASE WHEN s LIKE '%/%' THEN
CAST(split_part(s, '/', 1) AS double_precision)
/ CAST(split_part(s, '/', 2) AS double_precision)
ELSE
CAST(s AS DOUBLE PRECISION)
END CASE
END
Then you can ORDER BY fraction_to_number(weird_column)
If possible, I would revisit the data design. Is it all this complexity really necessary?
This postgres SQL does the trick:
select (parts[1] :: decimal) / (parts[2] :: decimal) as quotient
FROM (select regexp_split_to_array(number_value_in_string, '/') as parts from table) x
Here's a test of this code:
select (parts[1] :: decimal) / (parts[2] :: decimal) as quotient
FROM (select regexp_split_to_array('1/200', '/') as parts) x
Output:
0.005
Note that you would need to wrap this in a case statement to protect against divide-by-zero errors and/or array out of bounds issues etc if the column did not contain a forward slash
Note also that you could do it without the inner select, but you would have to use regexp_split_to_array twice (once for each part) and you would probably incur a performance hit. Nevertheless, it may be easier to code in-line and just accept the small performance loss.
I managed to solve my problem. Thanks all.
It goes something like this, in a single SQL. (I'm using POSTGRESQL)
It will sort a string coming in as either "#", "#.#" or "1/#"
SELECT id, number_value_in_string FROM table ORDER BY CASE WHEN position('1/' in number_value_in_string) = 1
THEN 1/substring(number_value_in_string from (position('1/' in number_value_in_string) + 2) )::numeric
ELSE number_value_in_string::numeric
END ASC, id
Hope this will help someone outhere in the future.