So, I have two tables in an Oracle database. The relevant column (let's call it field_x) is of type CLOB in table_a and VARCHAR2(510) in table_b.
If I run any of these queries, everything works fine:
SELECT cast(field_x AS VARCHAR2(510)) AS x FROM table_a WHERE some-condition;
SELECT field_x AS x FROM table_b WHERE some-condition;
But if I combine the output of those same query with a union, a problem arises:
SELECT cast(field_x AS VARCHAR2(510)) AS x FROM table_a WHERE some-condition
UNION
SELECT field_x AS x FROM table_b WHERE some-condition;
I'm getting this error:
ORA-12801: error signaled in parallel query server P00M, instance such-and-such
ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 4718, maximum: 4000)
What could be the reason? Each query works fine on its own, so it's not like there are any clob values longer than 510 characters.
It works with DBMS_LOB.substr explicitly called:
SELECT cast(DBMS_LOB.substr(field_x, 510, 1) AS VARCHAR2(510)) AS x FROM table_a WHERE some-condition
UNION
SELECT field_x AS x FROM table_b WHERE some-condition;
I have a report to create but there's a little problem I can't solve because the column(date) I generate has a different value. I use it in a subquery. My question is can I used a format so that I can manage to edit the value of the column? Please see the table below for reference,
My column(date) contains
date_columns
2019-06-20T11:09:15.674+00:00
2019-06-20T11:09:15.674+00:00
2019-06-20T11:09:15.674+00:00
2019-06-20T11:09:15.673+00:00
Now, my problem is it returned me ORA-01427: single-row subquery returns more than one row becaue of that 2019-06-20T11:09:15.673+00:00. Can I do a format to make it looked like 2019-06-20T11:09:15?
I tried the query below but nothing changed. It returned me a same error.
select distinct to_date(substr(dar.last_update_date,1,15),'YYYY-MM-DD HH:MI:SS')
select distinct to_date(dar.last_update_date,1,15,'YYYY-MM-DD HH:MI:SS')
Thanks!
2019-06-20T11:09:15.673+00:00 appears to be a string of a datetime in the official XML representation. We can turn it into an actual timestamp using to_timestamp_tz() and then cast the timestamp to a date:
select cast(
to_timestamp_tz('2019-06-20T11:09:15.673+00:00','YYYY-MM-DD"T"HH24:MI:SS:FFTZH:TZM')
as date)
from dual;
However, I'm not sure how this will resolve the ORA-01427: single-row subquery returns more than one row error. This exception occurs when we use a subquery like this …
where empno = ( select empno
from emp
where deptno = 30
and sal > 2300 )
… and the subquery returns more than one row because the WHERE clause is too lax. The solution is to fix the subquery's WHERE clause so it returns only one row (or use distinct in the subquery's projection if that's not possible).
I'm facing a problem when I try to use LAG function on CLOB column.
So let's assume we have a table
create table test (
id number primary key,
not_clob varchar2(255),
this_is_clob clob
);
insert into test values (1, 'test1', to_clob('clob1'));
insert into test values (2, 'test2', to_clob('clob2'));
DECLARE
x CLOB := 'C';
BEGIN
FOR i in 1..32767
LOOP
x := x||'C';
END LOOP;
INSERT INTO test(id,not_clob,this_is_clob) values(3,'test3',x);
END;
/
commit;
Now let's do a select using non-clob columns
select id, lag(not_clob) over (order by id) from test;
It works fine as expected, but when I try the same with clob column
select id, lag(this_is_clob) over (order by id) from test;
I get
ORA-00932: inconsistent datatypes: expected - got CLOB
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 1 Column: 16
Can you tell me what's the solution of this problem as I couldn't find anything on that.
The documentation says the argument for any analytic function can be any datatype but it seems unrestricted CLOB is not supported.
However, there is a workaround:
select id, lag(dbms_lob.substr(this_is_clob, 4000, 1)) over (order by id)
from test;
This is not the whole CLOB but 4k should be good enough in many cases.
I'm still wondering what is the proper way to overcome the problem
Is upgrading to 12c an option? The problem is nothing to do with CLOB as such, it's the fact that Oracle has a hard limit for strings in SQL of 4000 characters. In 12c we have the option to use extended data types (providing we can persuade our DBAs to turn it on!). Find out more.
Some of the features may not work properly in SQL when using CLOBs(like DISTINCT , ORDER BY GROUP BY etc. Looks like LAG is also one of them but, I couldn't find anywhere in docs.
If your values in the CLOB columns are always less than 4000 characters, you may use TO_CHAR
select id, lag( TO_CHAR(this_is_clob)) over (order by id) from test;
OR
convert it into an equivalent SELF JOIN ( may not be as efficient as LAG )
SELECT a.id,
b.this_is_clob AS lagging
FROM test a
LEFT JOIN test b ON b.id < a.id;
Demo
I know this is an old question, but I think I found an answer which eliminates the need to restrict the CLOB length and wanted to share it. Utilizing CTE and recursive subqueries, we can replicate the lag functionality with CLOB columns.
First, let's take a look at my "original" query:
WITH TEST_TABLE AS
(
SELECT LEVEL ORDER_BY_COL,
TO_CLOB(LEVEL) AS CLOB_COL
FROM DUAL
CONNECT BY LEVEL <= 10
)
SELECT tt.order_by_col,
tt.clob_col,
LAG(tt.clob_col) OVER (ORDER BY tt.order_by_col)
FROM test_table tt;
As expected, I get the following error:
ORA-00932: inconsistent datatypes: expected - got CLOB
Now, lets look at the modified query:
WITH TEST_TABLE AS
(
SELECT LEVEL ORDER_BY_COL,
TO_CLOB(LEVEL) AS CLOB_COL
FROM DUAL
CONNECT BY LEVEL <= 10
),
initial_pull AS
(
SELECT tt.order_by_col,
LAG(tt.order_by_col) OVER (ORDER BY tt.order_by_col) AS PREV_ROW,
tt.clob_col
FROM test_table tt
),
recursive_subquery (order_by_col, prev_row, clob_col, prev_clob_col) AS
(
SELECT ip.order_by_col, ip.prev_row, ip.clob_col, NULL
FROM initial_pull ip
WHERE ip.prev_row IS NULL
UNION ALL
SELECT ip.order_by_col, ip.prev_row, ip.clob_col, rs.clob_col
FROM initial_pull ip
INNER JOIN recursive_subquery rs ON ip.prev_row = rs.order_by_col
)
SELECT rs.order_by_col, rs.clob_col, rs.prev_clob_col
FROM recursive_subquery rs;
So here is how it works.
I create the TEST_TABLE, this really is only for the example as you should already have this table somewhere in your schema.
I create a CTE of the data I want to pull, plus a LAG function on the primary key (or a unique column) in the table partitioned and ordered in the same way I would have in my original query.
Create a recursive subquery using the initial row as the root and descending row by row joining on the lagged column. Returning both the CLOB column from the current row and the CLOB column from its parent row.
I am new to SQL and recently installed Oracle 11g. I read the post here on selecting all tables from user_tables. I'm trying to select a specific table and following some of the suggestions in the post does not appear to work.
The following executes fine and returns all tables available to me including a table named faculty_t:
select * from user_tables;
select * from dba_tables;
select * from all_tables;
desc faculty_t;
But I get error when I do the following:
select * from user_tables where table_name = FACULTY_T;
The first set of statements confirm that I do have a table named faculty_t. However, trying to select this table from user_tables, all_tables, or dba_tables does not appear to work for me right now. The error message reads something like:
ORA-00904: "FACULTY_T": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error at Line: 208 Column: 8
Any thoughts? Thanks!
String literals in SQL are wrapped in '. So:
select * from user_tables where table_name = 'FACULTY_T';
When you did a desc faculty_t, the SQL engine knew that a table name was expected at that spot (the syntax expects a table name there). But in your select query, sql is just looking for the value of a column that happens to have a string data type, so you need to use the ' for a string literal.
I have this query I am trying to run but I keep running into this error. I am trying to do a Where clause that compares the data (BLOB column) to :var2 which is a blob object.
Here is my code.
SELECT max(id)
INTO :var1
FROM table_name
where data = :var2;
Any suggestions to why I would be getting this ORA-00932 error?
I am comparing a blob to a blob column, shouldn't that be fine?
Thanks
They aren't simple types and you need to use a function to compare them.
SELECT max(id)
INTO :var1
FROM table_name
where dbms_lob.compare(data,:var2) = 0;