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

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.

Related

Access 10 sql query

I want to use LIKE operator in access 10 sql query with variable.
Example:
temporary variable var contains value bs
var = "bs"
I want to match every String that starts with value of temporary variable followed by zero or more numbers.
I am trying to fire the query:
select * from xyz where variety LIKE "#[tempvars]![var] + [0-9]*"
It is returning 0 records.
Thankz for the help.
You need to refer to your tempvar outside of the quotes, and use & for concatenation:
select * from xyz where variety LIKE "#" & [tempvars]![var] & "[0-9]*"
This will return all records where variety starts with a literal #, then whatever is in [tempvars]![var], then a number, and then any amount of characters.
You can check if that variety is available in your table or not. If that variety is available in your table then don't search with like operator and otherwise use like operator.

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 replace where clause dynamically in query (BIRT)?

In my report query I have a where clause that needs to be replaced dynamically based on the data chosen in the front end.
The query is something like :
where ?=?
I already have a code to replace the value - I created report parameter and linked to the value ? in the query.
Example:
where name=?
Any value of name that comes from front end replaces the ? in the where clause - this works fine.
But now I need to replace the entire clause (where ?=?). Should I create two parameters and link them to both the '?' ?
No, unfortunately most database engines do not allow to use a query parameter for handling a dynamic column name. This is for security considerations.
So you need to keep an arbitrary column name in the query:
where name=?
And then in "beforeOpen" script of the dataset replace 'name' with a report parameter value:
this.queryText=this.queryText.replace("name",params["myparameter"].value);
To prevent SQLIA i recommend to test the value of the parameter in this script. There are many ways to do this but a white list is the strongest test, for example:
var column=params["myparameter"].value;
if (column=="name" || column=="id" || column=="account" || column=="mycolumnname"){
this.queryText=this.queryText.replace("name",column);
}
In addition to Dominique's answer and your comment, then you'll just need a slightly more advanced logic.
For example, you could name your dynamic column-name-value pairs (column1, value1), (column2, value2) and so on. In the static text of the query, make sure to have bind variables for value1, value2 and so on (for example, with Oracle SQL, using the syntax
with params as (
select :value1 as value1,
:value2 as value2 ...
from dual
)
select ...
from params, my_table
where 1=1
and ... static conditions....
Then, in the beforeOpen script, append conditions to the query text in a loop as needed (the loop left as an exercise to the reader, and don't forget checking the column names for security reasons!):
this.queryText += " and " + column_name[i] + "= params.value" + i;
This way you can still use bind variables for the comparison values.

Non-integer constants in the ORDER BY clause

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);

Should I quote numbers in SQL?

I remember reading about quoting stuff when doing a SQL query and that when you quote something, it becomes a string. I also read that numbers should not be quoted. Now, I can't find that quotation and I need to refresh my memory to see if I should quote numbers.
You should not quote numbers if you want to treat them as numbers.
You're correct by remembering that it makes it a string.
SELECT 10 AS x
is perfectly legal and will return (in most database engines) a column of datatype int (or a variation thereof.)
If you do this:
SELECT '10' AS x
instead you'll get a textual data type. This might too be suitable in some cases, but you need to decide whether you want the result as text or as a number.
Here's an example, where quoting would produce inconsistent results (in MySQL):
select 1 < 1.0; // returns 0
select '1' < '1.0'; // returns 1
That's because the second comparison is performed using the current string collation rather than numerically.
It's better not to quote numbers, since that would just be an extra unnecessary step for the database to convert the string literal into a numeric value for comparison and could alter the meaning of comparisons.
This answer is for Microsoft SQL Server, in particular MSSQL 2008 R2.
In handwritten SQL I would never quote numbers (unless inserting a value into a varchar column where the string inserted just happens to be a number). But sometimes when generating SQL programmatically it can make life simpler to just quote everything. (This is in database maintenance scripts or library routines that work on any table, without knowing the column types in advance.)
I wondered whether doing so would impose a performance penalty. If I've used a quoted value in my SQL statement, the server must parse it as a string and then have to convert it to integer. But then, parsing SQL would involve converting strings to integers anyway. And the query parse time is usually only a small fraction of the total.
I ran some test statements looking like
insert into #t values (123, 123, 123), (123, 123, 123)
insert into #t values ('123', '123', '123'), ('123', '123', '123')
but with a larger number of columns in #t, a larger number of value tuples inserted in one go, and each statement repeated many times. I happened to use Perl for that:
$dbh = my_database_connection(); # using DBD::Sybase
$n = 20; # this many value tuples, and also repeated this many times
$v = "'123'";
# $v = 123; # uncomment this to insert without quoting
#cols = 'aa' .. 'zz';
#ds = map { "[$_] int not null" } #cols;
#vs = map { $v } #cols;
$" = ", ";
$dbh->do("create table #t (#ds)");
foreach (1 .. $n) {
$sql = 'insert into #t values ';
$sql .= "(#vs), " foreach 1 .. $n;
$sql =~ s/, \z//;
$dbh->do($sql);
}
but you can trivially write the same benchmark in any language. I ran this several times for the quoted case and for the unquoted, and observed no significant difference in speed. (On my setup a single run took about ten seconds; you can obviously change $n to make it faster or slower.)
Of course, the generated SQL is bigger if it has the redundant quote characters in it. It surely can't be any faster, but it does not appear to be noticeably slower.
Given this result, I will simplify my SQL-generation code to add single quotes around all values, without needing to know the data type of the column to be inserted into. (The code does still need to defend against SQL injection by making sure the input value doesn't itself contain the ' character, or otherwise quoting cleverly.)
I still don't recommend quoting numbers in SQL in the normal course of things, but if you find you have to do it, it doesn't appear to cause any harm. Similarly, in generated code I put [] around column names whether needed or not, but I consider that unnecessary cruft in handwritten SQL.
I don't know what you may have read, but don't quote numbers.
Obviously, don't forget to check to make sure any value you passed is really a number.
Well, at the risk of igniting a flame, may I respectfully disagree a little here that it is NEVER ok to use single quotes around a numeric value? It seems to me that it SOMETIMES makes sense to use single quotes around a numeric value. If col1 is an INT column, then (using vbscript as an example)
sql = "INSERT " & foo & " INTO col1 WHERE ID = 1"
and
sql = "INSERT '" & foo & "' INTO col1 WHERE ID = 1"
will BOTH, when sql is executed, insert any integer value of foo correctly. But what if you want 0 to be inserted when foo is not initialized? Using a quoted numeric expression like this prevents an error and handles the null case. Whether or not you think this is good practice, it is certainly true.
eh... no you shouldn't?
I assume you mean by quoting enclosing in ' like 'this'
INSERT INTO table (foo) VALUES (999); is perfectly legal as long as foo is an INT type collumn
INSERT INTO table (foo) VALUES('foo'); Inserts the string foo into the table. You can't do this on INT type tables of course.