select inside CLOB and get what it cotains - oracle

I am not sure if this is duplicated ,I havent find it in the search.
I have a table called mytable that has column STORY the type of this column is CLOB
mytable
The elder tree
Soldiers
Going for a hunt
The blue moon
If i write :
select story from mytable
I will have the result:
Mytable
1-clob
2-clob
3-clob
4-clob
What I want what inside CLOB , can I achieve that ?

dbms_lob.substr( clob, bytes, startbyte );
but in sql you can retrieve only 4000 bytes into varchar

Related

Why my table takes more spaces even it have less row then other table?

I have the following table
Create table my_source(
ID number(15) not null,
Col_1 Varchar 2(3000),
Col_2 Varchar 2(3000),
Col_3 Varchar 2(3000),
Col_4 Varchar 2(3000),
Col_5 Varchar 2(3000),
...
Col_90 Varchar 2(3000)
);
This table have 6,926,220 rows.
Now I am going to create two table based on this table.
Target1
Create table el_temp as
select
id,
Col_1,
Col_2,
Col_3,
Col_4,
Col_5,
Col_6,
Col_7,
Col_8,
Col_9,
Col_10,
Col_11,
Col_12
from
my_source;
Target2:
Create table el_temp2 as
select DISTINCT
id,
Col_1,
Col_2,
Col_3,
Col_4,
Col_5,
Col_6,
Col_7,
Col_8,
Col_9,
Col_10,
Col_11,
Col_12
from
my_source;
select count(*) from el_temp; -- 6926220
select count(*) from el_temp2; --6880832
The only difference between el_temp and el_temp2 is the "distinct" operator.
Now I got the following result from SQL Developer
It is a surprise result to me that EL_TEMP, the one with more rows have a smaller size, while the el_temp2 have less row but a bigger size.
Could anyone share me any reason and how to avoid this happen?
Thanks in advance!
The most likely cause is that the table has undergone some updates to existing rows over its lifetime.
By default, when you create a table, we reserve 10% of the space in each block for rows to grow (due to updates). As updates occur, that space is used up, so your blocks might be (on average) around 95% full.
When you do "create table as select" from that table to another, we will take those blocks and pad them out again to 10% free space, thus making it slightly larger.
If PCTFREE etc is unfamiliar to you, I've also got a tutorial video to get you started here
https://youtu.be/aOZMp5mncqA

Oracle CLOB column and LAG

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.

Oracle query looking for particular string format

Am working with an Oracle 11g db in which I need to run a query that returns all rows with values in a specific format.
I.e., I need to find all rows with a value like 'abc1234'. The actual values aren't important....what I need is to find all rows with the first 3 characters being alpha and the subsequent 4 characters all being numeric.
Any input would be much appreciated.
Might not be exact since I don't have an Oracle server handy to test but something like this should get you started in the right direction:
SELECT * FROM your_table WHERE REGEXP_LIKE(your_column, '([a-z]\3[0123456789]\4', 'i')
This will check all rows in your table where the specified column has any alphabet character A to Z three times followed by 4 numbers and return that list. The 'i' at the end just says ignore case on the alphabet part. You can choose to not have that option if you so wish.
Here are a couple links as well with more information on the regexp_like syntax:
Oracle SQL - REGEXP_LIKE contains characters other than a-z or A-Z
https://docs.oracle.com/cd/B28359_01/server.111/b28286/conditions007.htm#SQLRF00501
Try it this will work definitely:
Let's take a sample example:
For example, create a sample table
CREATE TABLE bob (
empno VARCHAR2(10) NOT NULL,
ename VARCHAR2(15) NOT NULL,
ssn VARCHAR2(10) NOT NULL);
Insert data into that table
Insert into bob ( empno,ename,ssn) values ('abC0123458','zXe5378023','0pl4783202');
Insert into bob ( empno,ename,ssn) values ('0123abcdef','a12dldfddd','Rns0101010');
Query to select the all the columns
select * from bob
where length(trim(translate(substr(empno,1,3),'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',' '))) IS NULL
AND
length(trim(translate(substr(empno,4,4),'0123456789',' '))) IS NULL;
To do the same thing on multiple columns use union operator
select * from bob
where length(trim(translate(substr(empno,1,3),'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',' '))) IS NULL
AND
length(trim(translate(substr(empno,4,4),'0123456789',' '))) IS NULL;
union
select * from bob
where length(trim(translate(substr(ename,1,3),'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',' '))) IS NULL
AND
length(trim(translate(substr(ename,4,4),'0123456789',' '))) IS NULL;

ORA-01465: invalid hex number in oracle while using BLOB

i am designing a database in oracle 11g. I have designed a table with fields,
CUST_ID, NUMBER(5) //this is a foreign key
Review, BLOB //to store big strings
Date, SYSDATE
now when i'm trying to insert data in the table like-
insert into "ReviewTable" values ( 3, 'hello, this is the first review',SYSDATE)
it gives [Err] ORA-01465: invalid hex number.
If someone can help me with the error?
you cast your string into BLOB, you can do this via package utl_raw.cast_to_raw or convert varchar to clob via to_clob('mystring') and then use procedure DBMS_LOB.convertToBlob in your code
but if you are going to use the fields for string why don`t save them as a CLOB?
Here are 2 examples below with BLOB and CLOB fields
BLOB
create table ReviewTable( CUST_ID NUMBER(5)
,Review BLOB
,Dt Date);
insert into ReviewTable values ( 3, utl_raw.cast_to_raw('hello, this is the first review'),SYSDATE);
CLOB
create table ReviewTable2( CUST_ID NUMBER(5)
,Review CLOB
,Dt Date);
insert into ReviewTable2 values ( 3, 'hello, this is the first review',SYSDATE);

how to insert picture or image into oracle database?

<code>
sql>CREATE TABLE Employees
(
Id int,
Name varchar(50) not null,
Photo varbinary(max) not null
)
</code>
This code is showing error like this:
photo varbinary(max) not null
*
ERROR at line 5:
ORA-00907: missing right parenthesis
Please help
You should use BLOB (Binary Large Object) which is ideal for storing multimedia content like images.
Check this out for storing images using BLOB.
You can create the table like below and insert into the table, below are the sample scripts for that
create table graphics_table (
bfile_id number,
bfile_desc varchar2(30),
bfile_loc bfile,
bfile_type varchar2(4));
INSERT INTO graphics_table
VALUES(4,'April Book of Days Woodcut',bfilename('GIF_FILES','APRIL.JPG'),'JPEG');
INSERT INTO graphics_table
VALUES(30,'',bfilename('GIF_FILES','SHAPIROS.GIF'),'GIF');
If u need more Info on this please refer to
http://www.dba-oracle.com/t_storing_insert_photo_pictures_tables.htm
First the question that has been posted is for SQL
varbinary(max) is a new datatype in sql2012
Cast f(x) will be used in order to convert the image into Binary format.
The insert query for the insertion of image is
insert into Employees values(1, 'ABC', cast('path\abc.jpeg') as varbinary(max));

Resources