How to use BOOLEAN type in SELECT statement
Asked Answered
S

11

67

I have a PL/SQL function with BOOLEAN in parameter:

function get_something(name in varchar2, ignore_notfound in boolean);

This function is a part of 3rd party tool, I cannot change this.

I would like to use this function inside a SELECT statement like this:

 select get_something('NAME', TRUE) from dual;

This does not work, I get this exception:

ORA-00904: "TRUE": invalid identifier

As I understand it, keyword TRUE is not recognized.

How can I make this work?

Sean answered 23/9, 2009 at 11:25 Comment(3)
I'm embarrassed on Oracle's behalf that you can't even do a comparison in a SQL statement with a boolean value returned from a PL/SQL block. You can't even wrap such a function in a CASE statement. The only sane answer is to upgrade your database to PostgreSQL, which deals with booleans in SQL statements beautifully.Begley
This is not quite true. Use the built-in sys.diutil.bool_to_int to convert BOOLEAN to INTEGER 0 or 1. Inside a stored procedure, there's no problem using BOOLEAN variables but that's not exactly the issue of concern here....Aerology
PostgreSQL has a boolean data type for columns. It is in this respect more modern than Oracle. Also, it has datatype TEXT for unlimited strings ...Bautram
H
32

You can build a wrapper function like this:

function get_something(name in varchar2,
                   ignore_notfound in varchar2) return varchar2
is
begin
    return get_something (name, (upper(ignore_notfound) = 'TRUE') );
end;

then call:

select get_something('NAME', 'TRUE') from dual;

It's up to you what the valid values of ignore_notfound are in your version, I have assumed 'TRUE' means TRUE and anything else means FALSE.

Hullda answered 23/9, 2009 at 11:32 Comment(4)
come on oracle, this is a really dumb limitationCarnassial
I'm curious as to how Oracle justifies this technically.Sn
in fact Ask Tom (oracles oracle) was condescending in his answer saying char(1) ('Y'/'N') "serves the same purpose". asktom.oracle.com/pls/asktom/…Vaivode
F_IS_YES - callable from any Oracle SQL Usage: SELECT * FROM WHATEVER WHEN F_IS_YES(SOMECOL)=1; Too limiting. How about using the built-in? create or replace function F_IS_YES(pVal IN VARCHAR2) return INTEGER is begin return(sys.diutil.bool_to_int( kdot_blp_util.f_is_yes(pVal)) ); EXCEPTION WHEN OTHERS THEN return 0; -- DISINCLINED TO ACQUIESCE TO YOUR REQUEST - MEANS NO end F_IS_YES; I tried this with the following VARCHAR2 values and they all returned the expected 0 or 1 : YES NO Y N T F y n true falseAerology
G
55

You can definitely get Boolean value from a SELECT query, you just can't use a Boolean data-type.

You can represent a Boolean with 1/0.

CASE WHEN (10 > 0) THEN 1  ELSE 0 END (It can be used in SELECT QUERY)

SELECT CASE WHEN (10 > 0) THEN 1  ELSE 0 END AS MY_BOOLEAN_COLUMN
  FROM DUAL

Returns, 1 (in Hibernate/Mybatis/etc 1 is true). Otherwise, you can get printable Boolean values from a SELECT.

SELECT CASE WHEN (10 > 0) THEN 'true' ELSE 'false' END AS MY_BOOLEAN_COLUMN
 FROM DUAL

This returns the string 'true'.

Grodin answered 4/11, 2011 at 14:34 Comment(1)
Completely irrelevant to the question though. The question wasn't "how do I use numbers instead of booleans".Begley
H
32

You can build a wrapper function like this:

function get_something(name in varchar2,
                   ignore_notfound in varchar2) return varchar2
is
begin
    return get_something (name, (upper(ignore_notfound) = 'TRUE') );
end;

then call:

select get_something('NAME', 'TRUE') from dual;

It's up to you what the valid values of ignore_notfound are in your version, I have assumed 'TRUE' means TRUE and anything else means FALSE.

Hullda answered 23/9, 2009 at 11:32 Comment(4)
come on oracle, this is a really dumb limitationCarnassial
I'm curious as to how Oracle justifies this technically.Sn
in fact Ask Tom (oracles oracle) was condescending in his answer saying char(1) ('Y'/'N') "serves the same purpose". asktom.oracle.com/pls/asktom/…Vaivode
F_IS_YES - callable from any Oracle SQL Usage: SELECT * FROM WHATEVER WHEN F_IS_YES(SOMECOL)=1; Too limiting. How about using the built-in? create or replace function F_IS_YES(pVal IN VARCHAR2) return INTEGER is begin return(sys.diutil.bool_to_int( kdot_blp_util.f_is_yes(pVal)) ); EXCEPTION WHEN OTHERS THEN return 0; -- DISINCLINED TO ACQUIESCE TO YOUR REQUEST - MEANS NO end F_IS_YES; I tried this with the following VARCHAR2 values and they all returned the expected 0 or 1 : YES NO Y N T F y n true falseAerology
K
26

From documentation:

You cannot insert the values TRUE and FALSE into a database column. You cannot select or fetch column values into a BOOLEAN variable. Functions called from a SQL query cannot take any BOOLEAN parameters. Neither can built-in SQL functions such as TO_CHAR; to represent BOOLEAN values in output, you must use IF-THEN or CASE constructs to translate BOOLEANvalues into some other type, such as 0 or 1, 'Y' or 'N', 'true' or 'false', and so on.

You will need to make a wrapper function that takes an SQL datatype and use it instead.

Kisser answered 23/9, 2009 at 11:32 Comment(0)
B
6

The BOOLEAN data type is a PL/SQL data type. Oracle does not provide an equivalent SQL data type (...) you can create a wrapper function which maps a SQL type to the BOOLEAN type.

Check this: http://forums.datadirect.com/ddforums/thread.jspa?threadID=1771&tstart=0&messageID=5284

Boxing answered 23/9, 2009 at 11:35 Comment(0)
M
3

With Oracle 12, you can use the WITH clause to declare your auxiliary functions. I'm assuming your get_something function returns varchar2:

with
  function get_something_(name varchar2, ignore_notfound number)
  return varchar2 
  is
  begin
    -- Actual function call here
    return get_something(name, not ignore_notfound = 0);
  end get_something_;

  -- Call auxiliary function instead of actual function
select get_something_('NAME', 1) from dual;

Of course, you could have also stored your auxiliary function somewhere in the schema as shown in this answer, but by using WITH, you don't have any external dependencies just to run this query. I've blogged about this technique more in detail here.

Mahdi answered 16/4, 2019 at 13:1 Comment(0)
E
2

Compile this in your database and start using boolean statements in your querys.

note: the function get's a varchar2 param, so be sure to wrap any "strings" in your statement. It will return 1 for true and 0 for false;

select bool('''abc''<''bfg''') from dual;

CREATE OR REPLACE function bool(p_str in varchar2) return varchar2 
 is
 begin

 execute immediate ' begin if '||P_str||' then
          :v_res :=  1;
       else
          :v_res :=  0;
       end if; end;' using out v_res;

       return v_res;

 exception 
  when others then 
    return '"'||p_str||'" is not a boolean expr.';
 end;
/
Erickaericksen answered 13/1, 2011 at 15:24 Comment(1)
This particular solution seems like a really a bad option. Why pay the overhead of getting the execute immediate to load and fire here? i guess I can understand the need for some sort of a universal boolean evaluator but not in a SQL statement.Aerology
U
2
select get_something('NAME', sys.diutil.int_to_bool(1)) from dual;
Unstoppable answered 27/12, 2011 at 7:20 Comment(1)
That produces "ORA-00902 invalid datatype"Mahdi
L
2

Oracle Database 23c has added the Boolean data type to SQL. So you can now call PL/SQL functions returning Boolean in queries as well as other Boolean expressions:

create or replace function gt_zero ( p int ) 
  return boolean as
begin
  return p > 0;
end;
/

select 
  gt_zero ( -1 ) minus_one, 
  gt_zero ( 1 ) one, 
  0 > 0 zero;
  
MINUS_ONE   ONE         ZERO
----------- ----------- -----------
FALSE       TRUE        FALSE
Lout answered 26/5, 2023 at 10:9 Comment(0)
M
0

The answer to this question simply put is: Don't use BOOLEAN with Oracle-- PL/SQL is dumb and it doesn't work. Use another data type to run your process.

A note to SSRS report developers with Oracle datasource: You can use BOOLEAN parameters, but be careful how you implement. Oracle PL/SQL does not play nicely with BOOLEAN, but you can use the BOOLEAN value in the Tablix Filter if the data resides in your dataset. This really tripped me up, because I have used BOOLEAN parameter with Oracle data source. But in that instance I was filtering against Tablix data, not SQL query.

If the data is NOT in your SSRS Dataset Fields, you can rewrite the SQL something like this using an INTEGER parameter:

__

<ReportParameter Name="paramPickupOrders">
  <DataType>Integer</DataType>
  <DefaultValue>
    <Values>
      <Value>0</Value>
    </Values>
  </DefaultValue>
  <Prompt>Pickup orders?</Prompt>
  <ValidValues>
    <ParameterValues>
      <ParameterValue>
        <Value>0</Value>
        <Label>NO</Label>
      </ParameterValue>
      <ParameterValue>
        <Value>1</Value>
        <Label>YES</Label>
      </ParameterValue>
    </ParameterValues>
  </ValidValues>
</ReportParameter>

...

<Query>
<DataSourceName>Gmenu</DataSourceName>
<QueryParameters>
  <QueryParameter Name=":paramPickupOrders">
    <Value>=Parameters!paramPickupOrders.Value</Value>
  </QueryParameter>
<CommandText>
    where 
        (:paramPickupOrders = 0 AND ordh.PICKUP_FLAG = 'N'
        OR :paramPickupOrders = 1 AND ordh.PICKUP_FLAG = 'Y' )

If the data is in your SSRS Dataset Fields, you can use a tablix filter with a BOOLEAN parameter:

__

</ReportParameter>
<ReportParameter Name="paramFilterOrdersWithNoLoad">
  <DataType>Boolean</DataType>
  <DefaultValue>
    <Values>
      <Value>false</Value>
    </Values>
  </DefaultValue>
  <Prompt>Only orders with no load?</Prompt>
</ReportParameter>

...

<Tablix Name="tablix_dsMyData">
<Filters>
  <Filter>
    <FilterExpression>
        =(Parameters!paramFilterOrdersWithNoLoad.Value=false) 
        or (Parameters!paramFilterOrdersWithNoLoad.Value=true and Fields!LOADNUMBER.Value=0)
    </FilterExpression>
    <Operator>Equal</Operator>
    <FilterValues>
      <FilterValue DataType="Boolean">=true</FilterValue>
    </FilterValues>
  </Filter>
</Filters>
Moonlit answered 14/8, 2018 at 15:41 Comment(0)
I
-3

How about using an expression which evaluates to TRUE (or FALSE)?

select get_something('NAME', 1 = 1) from dual
Intercut answered 23/9, 2009 at 11:38 Comment(0)
C
-5

PL/SQL is complaining that TRUE is not a valid identifier, or variable. Set up a local variable, set it to TRUE, and pass it into the get_something function.

Chaves answered 23/9, 2009 at 11:32 Comment(5)
No, Oracle SQL simply CANNOT process boolean values :-(Hullda
Plus, I want to use this function in a view definition, not inside a script.Sean
@Ula, Tony: Then I guess wrapping the function is the most suitable way.Chaves
@a_horse_with_no_name I'm not sure what your point is here. Yes, of course PL/SQL supports the Boolean type - the question shows that. But no, SQL does not. Hence "SQL simply CANNOT process Boolean values."Hullda
@a_horse_with_no_name er. no it doesn't?!Hullda

© 2022 - 2024 — McMap. All rights reserved.