Validate null columns values in a select statement in BigQuery - validation

I'm trying to make a select to a bigquery table, but I need to assign a default value to a column if it is null, because next in the process I need the default or the real item_id value, I was trying to use the CASE validation but I'm not pretty sure if I can use this clause for this purpose, and I'm getting the next error:
Expected end of input but got keyword case.
Select
p.item_id CASE WHEN item_id IS NULL THEN 'XXXXX' ELSE item_id END AS item_id,
from items
where -- rest of the query
Any ideas?

try this
Select
IFNULL(p.item_id,'XXXXX') AS item_id,
from items
where -- rest of the query
IFNULL() function in BigQuery
IFNULL(expr, null_result)
Description
If expr is NULL, return null_result. Otherwise, return expr. If expr is not NULL, null_result is not evaluated.
expr and null_result can be any type and must be implicitly coercible to a common supertype. Synonym for COALESCE(expr, null_result).
more details: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#ifnull

Use
isnull(yourcolumn,'')
--or
isnull(yourcolumn,99999999)
and you can put anything between those quotes. If the value is an int that won't work though. You will need to make it some default number, preferably something that would never be used like 9999999999.

Related

ORA-1008 if form variable referenced in ORDER BY Clause

TLDR; Is there anything I can set in an Oracle Form that would let me bind a placeholder to a Data Block's ORDER BY Clause?
I'm developing a form using Oracle Form Builder 10.1.2.3.0 (because it's interfacing with a system that makes other form types undesirable).
It has a Data Block with Query Data Source Type = Table.
Its WHERE Clause allows the user to be flexible in the search, producing rows of varying interest. I want rows with a perfect match to appear before those that are not.
To implement this specification, I wrote the form's WHERE Clause and ORDER BY Clause to reflect this SQL*Plus example:
var sf varchar2(30)
exec :sf := 'X'
with mdual as (
select case when level=1 then dummy else dummy || level end dummy
from dual
connect by level <= 2
)
select *
from mdual
where :sf is null or dummy like '%' || upper(:sf) || '%'
order by case when :sf = dummy then 0 else 1 end asc, dummy;
The form variable reference is not as simple as :sf and the WHERE Clause is a bit more complicated as is the ORDER BY Clause but this type of query is valid. When executed in SQL*Plus, it produces exactly the type of result I desire. You can reverse the first sort expression to prove it.
When I execute the form, I get an ORA-1008 until I comment the first ORDER BY expression.
My conclusion is that Oracle Forms binds placeholder references in a WHERE Clause but not an ORDER BY Clause.
I could experiment with setting the Query Data Source Type to Procedure and pass the procedure the filter field but a view has more utility than a procedure and so I'd prefer to keep using the view that I've defined for the Query Data Source Type.
Is there a way I can coerce Oracle Forms to do what I consider the right thing?
You can use SET_BLOCK_PROPERTY built-in function in order to make it dynamical and depending on a local or bind variable such as
DECLARE
v_orderby := ' CASE WHEN '||:sf||' = ''dummy'' THEN 0 ELSE 1 END, dummy';
BEGIN
SET_BLOCK_PROPERTY('block1',ORDER_BY, v_orderby);
EXECUTE_QUERY;
END;
which might be invoked from a trigger such as WHEN-NEW-BLOCK-INSTANCE after sending cursor to this block by using another action such as clicking on a button or pressing a key such as enter etc.

Return one variable from a SELECT inside a function

I'm trying to create a function that return a varchar, one of the fields form a select, the aggregation field. I'm getting the next error:
ORA-01422: exact fetch returns more than requested number of rows
What I understand is that the select produce more than one row before aggregating and this triggers the error when trying to put them 'into k, s, categories'
Here is the function:
FUNCTION get_cat(kind_id IN varchar, system_id IN Number) RETURN VARCHAR2
AS categories VARCHAR2(2000);
k STANDARDS.KIND_ID%TYPE;
s SEEDTEST_RESULT.SLRN_ID%TYPE;
BEGIN
SELECT STANDARDS.KIND_ID, SEEDTEST_RESULT.SLRN_ID,
listagg(CAT_LEVEL, ' ' ) within group (order by cat_level)
INTO k, s, categories
FROM STANDARDS, SEEDTEST_RESULT
WHERE STANDARDS.CL_PRIORITY = SEEDTEST_RESULT.CL_PRIORITY
AND SEEDTEST_RESULT.RESULT = 1
AND SEEDTEST_RESULT.TEST_TYPE = 'C'
AND STANDARDS.KIND_ID = trim(kind_id)
AND SEEDTEST_RESULT.SLRN_ID = system_id
GROUP BY STANDARDS.KIND_ID, SEEDTEST_RESULT.SLRN_ID;
RETURN categories;
END get_cat;
The select statement works outside the function when I run it with specific values for kind_id and system_id.
I've been trying to create a temp table so I can get the initial rows from the select and then return categories, but so far I haven't been able to find any helpful information for this particular case. Does anyone knows how can I do this, please?
Thank you.
The problem is with your variable names:
FUNCTION get_cat(kind_id IN varchar, ...
...
AND STANDARDS.KIND_ID = trim(kind_id)
You have a column called kind_id and the query will use that in preference to the PL/SQL variable of the same name.
From the documentation:
If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence.
So you aren't matching the passed-in value, you're actually finding all rows which match system_id for any value of kind_id. (Except null, and if they have leading/trailing whitespace...)
Change your variable names so they do not clash and there is no confusion. It's common to prefix passed-in argument with, say, a p prefix so you'd be comparing with = p_kind_id, and local variables with an l prefix.
If you really want to keep the names you have, you can also prefix the references to those with the function name:
AND STANDARDS.KIND_ID = trim(get_cat.kind_id)

Make condition only if "something" - Query Oracle

i'm with a problem in a query.
I have a table called "store" that I need to query.
Select s.store_name
from store s
where s.store = case
when p_store != 0 then
p_store
else
s.store
end;
This should work but as I have "stores" with characters (-) in column and this is defined as number, that query raise an exception: ORA-01722: invalid number.
So I want to do something like this in query:
IF p_store != 0 then
select store_name from store where store = p_store
else
select store_name from store;
Is it possible?
Thanks!
EDIT:
The query that I wrote above was an example of the query I was running.
The exception was raised because another column (too much hours in front of PC :-( ).
This table have a column that's varchar2(15) and I was doing this condition:
(...)AND S.CODE > 4 (...)
The correct condition that I want to do is:
(...)AND LENGTH(S.CODE) > 4
Thank you all!
As far as I understand you have varchar2 s.store which in fact contains numbers so Oracle tries to compare it casting to numbers but at some point it gets - and throws an exception. What you should do is update on table replacing - by null. But if you don't want to do that you can try to make case return varchar2
Select s.store_name
from store s
where s.store = case
when to_char(p_store) != '0' then
to_char(p_store)
else
s.store
end;
I am guessing you are running the query in a plsql block (as cursor?). In that case dynamic sql is the way to go. check out REF CURSOR too (google!).

Return Boolean value when table has data in the specified range

I need a query to return boolean when there's table has data in the given range.
Assume table
Customer
[User ID, Name, Date, Products_Purchased]
I'm trying to do:
select case when exists(
select Date, count(*)
from Customer
where date between '2015-08-03' and '2015-08-05'
)
then cast(1 as BIT)
else case(0 as BIT)end;
This is throwing an error near "select Date".
However, weird part is the inner query is running perfectly fine.
Im wondering if im missing out something here !
What about something more straightforward e.g.
select case when count(*) >0 then 1 else 0 end as HIT
from ... where ...
That way you don't have to bother about Hive assuming that EXISTS implies a correlated sub-query, automagically translated into a MapJoin, i.e. a Java HashMap shuffled to the 2nd line of Mappers jobs, etc. Not exactly your use case.
Then it's not useful to compute the exact count, so the query could be refined as
select case when count(*) >0 then 1 else 0 end as HIT
from
(select ... from ... where ... limit 1) X
[Edit] There is no "bit" datatype in Hive. But the default "int" should be OK if you just want a return flag (zero / non-zero)

oracle query error: exact fetch return more than requested no of rows

I have two tables seatinfo(siid,seatno,classid,tsid) and booking (bookid,siid,date,status).
I've input parameter bookDate,v_tsId ,v_clsId. I need exactly one row (bookid) to return. This query is not working. I don't no why. How can I fix it?
select bookid
into v_bookid
from booking
where (to_char(booking.bookdate,'dd-mon-yy'))=(to_char(bookDate,'dd-mon-yy'))
and status=0
and rownum <= 1
and siid in(select siid
from seatinfo
where tsid=v_tsId
and classid= v_clsId);
I also tried this:
select bookid
into v_bookid
from booking,
seatinfo
where booking.siid=seatinfo.siid
and (to_char(booking.bookdate,'dd-mon-yy'))=(to_char(bookDate,'dd-mon-yy'))
and booking.status=0
and rownum <= 1
and seatinfo.tsid=v_tsId
and seatinfo.classid= v_clsId;
Are you saying that you get an "ORA-01422: exact fetch returns more than requested number of rows" when you run both of those queries? That seems highly unlikely since you're including the predicate rownum <= 1. Can you cut and paste from a SQL*Plus session that runs just this query in a PL/SQL block and generates the error?
If you are not complaining about the error you mention in the title, and the problem is just that you're not getting the data you expect, the likely problem is that you apparently have a bookDate parameter that has the same name as a column in your table. That is not going to work. When you say
(to_char(booking.bookdate,'dd-mon-yy'))=(to_char(bookDate,'dd-mon-yy'))
you presumably mean to compare the bookDate column in the booking table against the bookDate parameter. But since column names have precedence over local variables, the left-hand side of your expression is also looking at the bookDate column in the booking table. So you're comparing a column to itself. It would make much more sense to change the name of the parameter (to, say, p_bookDate) and then write
booking.bookDate = p_bookDate
or, if you want to do the comparison ignoring the time component of the dates
trunc( booking.bookDate ) = trunc( p_bookDate )

Resources