Why does this SQLite UPDATE statement write changes to all records in the table? - sqlite

This query returns 40319 records:
SELECT artist,
title,
composer AS alib_composer,
master.composer AS master_composer
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %";
Translating above into the following UPDATE query results in all records in alib being updated. Could someone help me understand why this is the case?
UPDATE alib
SET composer = (
SELECT composer
FROM master
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %"
);
I suspect I know why, but turning the update into something like this:
UPDATE alib
SET composer = master.composer
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %";
causes SQLite to complain:
Error while executing SQL query on database 'x': no such column: master.composer

Because there is no WHERE clause on the outer/main UPDATE SQL i.e. it is basiclly
UPDATE alib SET composer = the_result_of_the_subquery;
i.e. UPDATE every row.
You want a WHERE clause to say which rows to update along the lines of :-
UPDATE alib SET composer = the_result_of_the_subquery WHERE ??????;
Or to use your code :-
UPDATE alib
SET composer = (
SELECT composer
FROM master
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %"
)
WHERE the_expression_to_restrict_which_rows_are_updated
;
This hasn't been fully tested but this may be solution you are looking for :-
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
UPDATE alib
SET composer =
(
SELECT cte.master_composer FROM cte WHERE cte.arowid = alib.rowid
)
WHERE alib.rowid IN (SELECT arowid FROM cte);
this uses a Common Table Expresssion(CTE) (temporay table that exists just for the query).
It utlises the rowid (a hidden column that every table has other than WITHOUT ROWID tables).
That is the CTE is based upon your original query that extracts the rows from alib that need to be updated. It only needs the composer from the master table and the rowid of the alib table for the update.
The UPDATE sets the composer to the value of the master_composer column of the respective row from the CTE according to the rowid of the row being updated.
The UPDATEs are only applied to rows that have a matching row in the CTE.
Testing (limited)
The following SQL was used for testing :-
DROP TABLE IF EXISTS alib;
DROP TABLE IF EXISTS master;
CREATE TABLE IF NOT EXISTS alib (__path,l_title,composer);
CREATE TABLE IF NOT EXISTS master (__path,title,artist,composer);
INSERT INTO alib VALUES
('path1','this','bert'),
('path2','something else','Joe'),
('path2','something else','Joe'), -- duplicate likely irrelevant but still updated
('path2','something else','Joe Someone'), -- already has space in composer skipped
('path100','an so on','x') -- no equivalent in master
;
INSERT INTO master VALUES
('path1','this','fred','bert'), -- ignored as no space
('path1','this','fred bloggs','Julia smith'),
('path2','something else','Alison','Joe Brown')
;
/* DEMO OF EXTRACTED ROWS */
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
SELECT * FROM cte;
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
UPDATE alib
SET composer =
(
SELECT cte.master_composer FROM cte WHERE cte.arowid = alib.rowid
)
WHERE alib.rowid IN (SELECT arowid FROM cte);
SELECT * FROM alib;
DROP TABLE IF EXISTS alib;
DROP TABLE IF EXISTS master;
Testing Results
The extracted data :-
alib table after UPDATES :-

Related

Use placeholders and $wpdb->prepare(); found interpolated variable $now

I have a problem with placeholders in $wpdb->get_results. With the code below I have all the results correctly but I have an error when I use the code sniffer
$now = current_time('mysql', true);
$allPosts = $wpdb->get_results("
SELECT DISTINCT
YEAR(post_date_gmt) AS `year`,
MONTH(post_date_gmt) AS `month`,
MAX(post_date_gmt) AS last_mod,
count(ID) AS posts
FROM
$wpdb->posts
WHERE
post_date_gmt < '$now'
AND post_status = 'publish'
AND post_type = 'post'
GROUP BY
YEAR(post_date_gmt),
MONTH(post_date_gmt)
ORDER BY
post_date_gmt DESC
");
I tried to change with %s and $now in the end but no results are shown
$allPosts = $wpdb->get_results("
SELECT DISTINCT
YEAR(post_date_gmt) AS `year`,
MONTH(post_date_gmt) AS `month`,
MAX(post_date_gmt) AS last_mod,
count(ID) AS posts
FROM
$wpdb->posts
WHERE
post_date_gmt < %s
AND post_status = 'publish'
AND post_type = 'post'
GROUP BY
YEAR(post_date_gmt),
MONTH(post_date_gmt)
ORDER BY
post_date_gmt DESC
", $now);
I know I can resolve it by omitted post_date_gmt < %s but I'd like to know how I can resolve it with post_date_gmt < %s?

CREATE OR REPLACE PROCEDURE proc_video_search

Create a procedure called proc_video_search to search for a video and display the name, copy ID, format, and status of the video’s copies. In addition, the checkout dates and due dates are also displayed for unreturned copies. The damaged copies (Status = 'D') are excluded in your output. Sort your output by the video name (Name) and then the copy ID (CopyID).
$ CREATE OR REPLACE PROCEDURE proc_video_search (
p_VideoName VARCHAR2,
p_FormatName VARCHAR2 DEFAULT NULL) as
v_Count NUMBER;
v_TotalCopies NUMBER; v_Avalb NUMBER;v_FormatName VARCHAR2(100);
v_VideoName VARCHAR2(100); v_CopyID VARCHAR2(100);v_DueDate DATE;
v_Status VARCHAR2(100); v_CheckoutDate DATE;
CURSOR asdf IS
SELECT T_VIDEO.Name, T_COPY.CopyID, Status,T_VIDEO_FORMAT.NAME
FROM T_VIDEO
INNER JOIN T_COPY ON T_VIDEO.VideoID = T_COPY.VideoID
INNER JOIN T_VIDEO_FORMAT ON T_VIDEO_FORMAT.FormatID =
T_VIDEO.FormatID
WHERE Status !='D' AND UPPER(T_VIDEO.Name) like '%' ||
UPPER(p_VideoName) || '%'
OR UPPER(T_VIDEO_FORMAT.NAME)= UPPER(p_FormatName)
ORDER BY T_VIDEO.Name, T_COPY.CopyID;
BEGIN
SELECT COUNT(*)
INTO v_Count
FROM T_VIDEO
WHERE UPPER(T_VIDEO.Name) like '%' || UPPER(p_VideoName) || '%' ;
IF v_count = 0 THEN
DBMS_OUTPUT.PUT_LINE('**** '||v_Count|| ' results found for ' ||
p_VideoName||'. *****');
RETURN;
END IF;
SELECT count(T_COPY.CopyID) INTO v_TotalCopies
FROM T_COPY INNER JOIN T_VIDEO ON T_COPY.VideoID = T_VIDEO.VideoID
INNER JOIN T_VIDEO_FORMA ON T_VIDEO_FORMAT.FormatID =
T_VIDEO.FormatID
WHERE Status !='D' AND UPPER(T_VIDEO.Name) like '%' ||
UPPER(p_VideoName) ||'%'
OR UPPER(T_VIDEO_FORMAT.NAME)=UPPER(p_FormatName);
SELECT count(T_COPY.CopyID)INTO v_Avalb FROM T_COPY
INNER JOIN T_VIDEO ON T_COPY.VideoID = T_VIDEO.VideoID
INNER JOIN T_VIDEO_FORMAT ON T_VIDEO_FORMAT.FormatID =
T_VIDEO.FormatID
WHERE Status ='A' AND UPPER(T_VIDEO.Name) like '%' ||
UPPER(p_VideoName) ||'%'
OR UPPER(T_VIDEO_FORMAT.NAME)=UPPER(p_FormatName);
IF v_TotalCopies >=0 THEN
IF p_FormatName IS NULL THEN
DBMS_OUTPUT.PUT_LINE(v_TotalCopies||' results found for '||
p_VideoName||' . (Available copies:'|| v_Avalb|| ')' );
ELSE
DBMS_OUTPUT.PUT_LINE(v_TotalCopies||' results found for '||
p_VideoName||'('|| p_FormatName||') . (Available copies:'||
v_Avalb|| ')' );
end if;
OPEN asdf;
LOOP
FETCH asdf INTO v_VideoName, v_CopyID, v_Status,
v_FormatName ; exit when asdf%NOTFOUND ;
SELECT COUNT(CheckoutDate)
INTO v_Count FROM T_RENTAL WHERE CopyID = v_CopyID;
IF v_Count = 1 THEN
SELECT CheckoutDate,DueDate
INTO v_CheckoutDate,v_DueDate
FROM T_RENTAL
WHERE CopyID = v_CopyID;
end if;
DBMS_OUTPUT.PUT_LINE(RPAD('-', 53, '-'));
DBMS_OUTPUT.PUT_LINE(RPAD('Name:',30) || RPAD(v_VideoName,15));
DBMS_OUTPUT.PUT_LINE(RPAD('CopyID:',30) || RPAD(v_CopyID,15));
DBMS_OUTPUT.PUT_LINE(RPAD('Format:',30) ||
RPAD(v_FormatName,15));
IF v_Status = 'A' THEN v_Status := 'Available';END IF;
IF v_Status = 'R' THEN v_Status := 'Rented'; END IF;
DBMS_OUTPUT.PUT_LINE(RPAD('Status:',30) || RPAD(v_Status,15));
IF v_Status ='Available' THEN
DBMS_OUTPUT.PUT_LINE(RPAD('CheckoutDate:',30)
||'****************************');
DBMS_OUTPUT.PUT_LINE(RPAD('DueDate:',30)
||'****************************');
ELSE
DBMS_OUTPUT.PUT_LINE(RPAD('CheckoutDate:',30)
||RPAD(TO_CHAR(v_CheckoutDate, 'DD-MON-YYYY'),15));
DBMS_OUTPUT.PUT_LINE(RPAD('DueDate:',30) ||RPAD(TO_CHAR(
v_DueDate, 'DD-MON-YYYY'),15));
END IF; END LOOP; CLOSE asdf; END IF; END proc_video_search ;
EXEC proc_video_search('ANOTHER', 'DVD')`
enter image description here
The problem is with this line of your cursor asdf
OR UPPER(T_VIDEO_FORMAT.NAME)= UPPER(p_FormatName)
Because it says OR, the query can choose to ignore this criteria if it evaluates to false. That is why you are getting results with all the formats; it ignores the filtering.
You have to wrap the OR statement in another AND clause, like so
WHERE Status !='D'
AND UPPER(T_VIDEO.Name) like '%' || UPPER(p_VideoName) || '%'
AND ( /* OR clause here */ )
And then you can handle the case of p_formatName being null or not.

SQL Server Count Occurrences of a value of colounns

Thank you for taking time to read this.
I have a ServiceDetails Table which have columns like
ID, ServiceID , ClientID... , Status ,IsFollowUp
and Services have
ID, Date , CityID, AreaID
Now when a service request is entered , its status is either 'pending', 'Completed','testing', or 'indeteriminent'.
Now end user wants a report that
City, Area , TotalServices , Total Completed without followup , Total Completed at First followup, Total Completed at 2nd followup ... , Total Completed at Fifth followup
I have Completed uptill now, Total Completed without followup but how do I calculate the Completed services followups count.
CREATE TABLE #TEMP#(
[ID] int PRIMARY KEY IDENTITY,
[Area] varchar(250),
[City] varchar(250),
[Total] int,
[WithoutFollowup] int,
[FirstFollowup] int,
[SecondFollowup] int,
[ThirdFollowup] int,
[FourthFollowup] int,
[FifthFollowup] int
);
DECLARE #AreaID AS bigint = 0
DECLARE #CityID AS bigint = 0
DECLARE #AreaName AS nvarchar(250) = ''
DECLARE #CityName AS nvarchar(250) = ''
DECLARE #VCCTDetailsID AS bigint = NULL, #ClientID AS bigint = NULL
,#TotalTests as int, #WithoutFollowup as int, #FirstFollowup as int,#SecondFollowup as int, #ThirdFollowup as int, #FourthFollowup as int, #FifthFollowup as int
,#Org as varchar(250),#City as varchar(250)
DECLARE cur CURSOR FOR
SELECT Areas.ID, Areas.Name, Cities.ID, Cities.CityName
FROM [dbo].[Areas]
INNER JOIN [dbo].[AreaCities] ON Areas.ID = AreaCities.AreaID
INNER JOIN [dbo].[Cities] ON AreaCities.CityID = Cities.ID
INNER JOIN [dbo].[States] ON States.ID = Cities.StateID
INNER JOIN [dbo].[Countries] ON Countries.ID = States.CountryID
WHERE [Areas].[IsActive] = 1
AND [Cities].[IsActive] = 1
AND [Areas].[CountryID] = 168
OPEN cur
FETCH NEXT FROM cur INTO #AreaID, #AreaName, #CityID, #CityName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Total = (
SELECT COUNT(1)
FROM [dbo].[ServiceDetails]
INNER JOIN [dbo].[Services] ON [ServiceDetails].[ServiceID] = [Services].[ID]
Where [ServiceDetails].[Status] !='Testing'
AND [ServiceDetails].[Status] !='Pending'
AND [Services].[AreaID] = #AreaID
AND [Services].[CityID] = #CityID
GROUP BY [Services].[AreaID],[Services].[CityID]
)
SET #WithoutFollowup = (
SELECT COUNT(1)
FROM [dbo].[ServiceDetails]
INNER JOIN [dbo].[Services] ON [ServiceDetails].[ServiceID] = [Services].[ID]
Where [ServiceDetails].[Status] !='completed'
AND [ServiceDetails].[IsFollowUp] = 'false'
AND [Services].[AreaID] = #AreaID
AND [Services].[CityID] = #CityID
GROUP BY [Services].[AreaID],[Services].[CityID]
)
SET #FirstFollowup = (
SELECT COUNT(1)
FROM [dbo].[ServiceDetails]
INNER JOIN [dbo].[Services] ON [ServiceDetails].[ServiceID] = [Services].[ID]
Where [ServiceDetails].[Status] !='completed'
AND [ServiceDetails].[IsFollowUp] = 'True'
GROUP BY [Services].[AreaID],[Services].[CityID]
)
INSERT #TEMP# ([Org],[City],[Total],[WithoutFollowup],[FirstFollowup],[SecondFollowup],[ThirdFollowup],[FourthFollowup],[FifthFollowup])
VALUES(#AreaName,#CityName,#Total,#WithoutFollowup,#FirstFollowup,#SecondFollowup,#ThirdFollowup,#FourthFollowup,#FifthFollowup);
FETCH NEXT FROM cur INTO #AreaID, #AreaName, #CityID, #CityName
END
CLOSE cur
DEALLOCATE cur
SELECT * FROM #TEMP#
DROP TABLE #TEMP#
I've accomplished this task using rownumbers and another temporary Table inside the cursor
INSERT INTO #Services#
SELECT ROW_NUMBER() OVER (ORDER BY [Services].[Date]) as 'RowNo',[ServiceDetails].* , [Services].[Date]
FROM [ServiceDetails]
INNER JOIN [Services] ON [Services].[ID] = [ServiceDetails].[VCCTsServiceID]
INNER JOIN [Clients] ON [Clients].[ID] = [ServiceDetails].[ClientID]
WHERE [Clients].[ID] LIKE #ClientID
ORDER BY [Services].[Date]
This #Services# is the exact replica of ServiceDetails table. Now we have all the services given to the client with rownumber and Date. It is sorted on date so we get the followups exactly when they are done. Now you can query what you want.
SET #TotalServices = ( SELECT COUNT(*) FROM #Services# )
SET #FirstSericeDate = (SELECT [#Services#].[Date] FROM #Services# WHERE [#Services#].[RowNo] = 1 )
SET #Status = (SELECT [#Services#].[Status] FROM #Services# WHERE [#Services#].[RowNo] = 1 )
SET #Date1 = (SELECT [#Services#].[Date] FROM #Services# WHERE [#Services#].[RowNo] = 2 )
SET #Status1 = (SELECT [#Services#].[Status] FROM #Services# WHERE [#Services#].[RowNo] = 2)
Then insert your variables into main temptable for reporting
INSERT #TEMP# ([RegNo], . . . [Status], Date1], [Status1] . .)
VALUES(#RegNo, . .. #Status, #Date1 , #Status1, . . );
TRUNCATE TABLE #Services#
FETCH NEXT FROM cur INTO #RegNo

Get Installation Sequence of Oracle Objects

Ok, I have a complex recursion problem. I want to get a dependecy installation sequence of all of my objcts (all_objects table) in my Oracle 11g database.
First I have created a view holding all dependencies
create or replace
view REALLY_ALL_DEPENDENCIES as
select *
from ALL_DEPENDENCIES
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
from all_indexes
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
from all_constraints p
join all_constraints f
on F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME
and F.CONSTRAINT_TYPE = 'R'
and p.constraint_type='P'
;
/
EDIT
I have tried do concate all dependencies by using this function:
create
or replace
function dependency(
i_name varchar2
,i_type varchar2
,i_owner varchar2
,i_level number := 0
,i_token clob := ' ') return clob
is
l_token clob := i_token;
l_exist number := 0;
begin
select count(*) into l_exist
from all_objects
where object_name = i_name
and object_type = i_type
and owner = i_owner;
if l_exist > 0 then
l_token := l_token || ';' || i_level || ';' ||
i_name || ':' || i_type || ':' || i_owner;
else
-- if not exist function recursion is finished
return l_token;
end if;
for tupl in (
select distinct
referenced_name
,referenced_type
,referenced_owner
from REALLY_ALL_DEPENDENCIES
where name = i_name
and type = i_type
and owner = i_owner
)
loop
-- if cyclic dependency stop and shout!
if i_token like '%' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '%' then
select count(*) into l_exist
from REALLY_ALL_DEPENDENCIES
where name = tupl.referenced_name
and type = tupl.referenced_type
and owner = tupl.referenced_owner;
if l_exist > 0 then
return '!!!CYCLIC!!! (' || i_level || ';' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '):' || l_token;
end if;
end if;
-- go into recursion
l_token := dependency(
tupl.referenced_name
,tupl.referenced_type
,i_owner /* I just want my own sources */
,i_level +1
,l_token);
end loop;
-- no cyclic condition and loop is finished
return l_token;
end;
/
And I can query through
select
object_name
,object_type
,owner
,to_char(dependency(object_name, object_type, owner)) as dependecy
from all_objects
where owner = 'SYSTEM'
;
Ok, maybe it is something like "cheating" but you can not do cyclic dependencies at creation time. So at least as a human beeing I am only able to create one object after another :-) And this sequence should be "reverse engineer able".
Now I am more interested in a solution than before ;-) And it is still about the tricky part ... "How can I select all soures from a schema orderd by its installation sequence (dependent objects list prior the using object)"?
It is just some kind of sorting problem, insn't it?
Usually you "cheat" by creating the objects in a particular order. For example, you might make sequences first (they have zero dependencies). Then you might do tables. After that, package specs, then package bodies, and so on.
Keep in mind that it is possible to have cyclic dependencies between packages, so there are cases where it will be impossible to satisfy all dependencies at creation anyway.
What's the business case here? Is there a real "problem" or just an exercise?
EDIT
The export tool we use exports objects in the following order:
Database Links
Sequences
Types
Tables
Views
Primary Keys
Indexes
Foreign Keys
Constraints
Triggers
Materialized Views
Materialized View Logs
Package Specs
Package Bodies
Procedures
Functions
At the end, we run the dbms_utility.compile_schema procedure to make sure everything is valid and no dependencies are missed. If you use other object types than these, I'm not sure where they'd go in this sequence.
Ok, I had some time to look at the job again and I want to share the results. Maybe anotherone comes across this thread searching for a solution. First of all I did the SQLs as SYS but I think you can do it in every schema using public synonyms.
The Procedure "exec obj_install_seq.make_install('SCOTT');" makes a clob containing a sql+ compatible sql file, assuming your sources are called "object_name.object_type.sql". Just spool it out.
Cheers
Chris
create global temporary table DEPENDENCIES on commit delete rows as
select * from ALL_DEPENDENCIES where 1=2 ;
/
create global temporary table install_seq(
idx number
,seq number
,iter number
,owner varchar2(30)
,name varchar2(30)
,type varchar2(30)
) on commit delete rows;
/
create global temporary table loop_chk(
iter number
,lvl number
,owner varchar2(30)
,name varchar2(30)
,type varchar2(30)
) on commit delete rows;
/
create or replace package obj_install_seq is
procedure make_install(i_schema varchar2 := 'SYSTEM');
end;
/
create or replace package body obj_install_seq is
subtype install_seq_t is install_seq%rowtype;
type dependency_list_t is table of DEPENDENCIES%rowtype;
procedure set_list_data(i_schema varchar2 := user)
is
l_owner varchar2(30) := i_schema;
begin
-- collect all dependencies
insert into DEPENDENCIES
select *
from (select *
from ALL_DEPENDENCIES
where owner = l_owner
and referenced_owner = l_owner
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
from all_indexes
where owner = l_owner
and table_owner = l_owner
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
from all_constraints p
join all_constraints f
on F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME
and F.CONSTRAINT_TYPE = 'R'
and p.constraint_type='P'
and p.owner = f.owner
where p.owner = l_owner
) all_dep_tab;
-- collect all objects
insert into install_seq
select rownum, null,null, owner, object_name, object_type
from (select distinct owner, object_name, object_type, created
from all_objects
where owner = l_owner
order by created) objs;
end;
function is_referencing(
i_owner varchar2
,i_name varchar2
,i_type varchar2
,i_iter number
,i_level number := 0
) return boolean
is
l_cnt number;
begin
select count(*) into l_cnt
from loop_chk
where name = i_name
and owner = i_owner
and type = i_type
and iter = i_iter
and lvl < i_level;
insert into loop_chk values(i_iter,i_level,i_owner,i_name,i_type);
if l_cnt > 0 then
return true;
else
return false;
end if;
end;
procedure set_seq(
i_owner varchar2
,i_name varchar2
,i_type varchar2
,i_iter number
,i_level number := 0)
is
-- l_dep all_dependencies%rowtype;
l_idx number;
l_level number := i_level +1;
l_dep_list dependency_list_t;
l_cnt number;
begin
-- check for dependend source
begin
select * bulk collect into l_dep_list
from dependencies
where name = i_name
and owner = i_owner
and type = i_type;
if l_dep_list.count <= 0 then
-- recursion finished
return;
end if;
end;
for i in 1..l_dep_list.count loop
if is_referencing(
l_dep_list(i).referenced_owner
,l_dep_list(i).referenced_name
,l_dep_list(i).referenced_type
,i_iter
,i_level
) then
-- cyclic dependecy
update install_seq
set seq = 999
,iter = i_iter
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type;
else
--chek if sequence is earlier
select count(*) into l_cnt
from install_seq
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type
and seq > l_level *-1;
-- set sequence
if l_cnt > 0 then
update install_seq
set seq = l_level *-1
,iter = i_iter
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type;
end if;
-- go recusrion
set_seq(
l_dep_list(i).referenced_owner
,l_dep_list(i).referenced_name
,l_dep_list(i).referenced_type
,i_iter + (i-1)
,l_level
);
end if;
end loop;
end;
function get_next_idx return number
is
l_idx number;
begin
select min(idx) into l_idx
from install_seq
where seq is null;
return l_idx;
end;
procedure make_install(i_schema varchar2 := 'SYSTEM')
is
l_obj install_seq_t;
l_idx number;
l_iter number := 0;
l_install_clob clob := chr(10);
begin
set_list_data(i_schema);
l_idx := get_next_idx;
while l_idx is not null loop
l_iter := l_iter +1;
select * into l_obj from install_seq where idx = l_idx;
update install_seq set iter = l_iter where idx = l_idx;
update install_seq set seq = 0 where idx = l_idx;
set_seq(l_obj.owner,l_obj.name,l_obj.type,l_iter);
l_idx := get_next_idx;
end loop;
for tupl in ( select * from install_seq order by seq, iter, idx ) loop
l_install_clob := l_install_clob || '#' ||
replace(tupl.name,' ' ,'') || '.' ||
replace(tupl.type,' ' ,'') || '.sql' ||
chr(10);
end loop;
l_install_clob := l_install_clob ||
'exec dbms_utility.compile_schema(''' || upper(i_schema) || ''');';
-- do with the install file what you want
DBMS_OUTPUT.PUT_LINE(dbms_lob.substr(l_install_clob,4000));
end;
end;
/

Search specific value in all field in oracle table

I want to search some keyword in table but I don't know to which column it is belonging to. I have got one of query for that as follows:
variable val varchar2(10)
exec :val := 'KING'
PL/SQL procedure successfully completed.
SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword",
SUBSTR (table_name, 1, 14) "Table",
SUBSTR (column_name, 1, 14) "Column" FROM cols,
TABLE (xmlsequence (dbms_xmlgen.getxmltype ('select '
|| column_name
|| ' from '
|| table_name
|| ' where upper('
|| column_name
|| ') like upper(''%'
|| :val
|| '%'')' ).extract ('ROWSET/ROW/*') ) ) t
ORDER BY "Table"
Searchword Table Column
KING EMP ENAME
but I am not getting appropriate output.I only got output as:
PL/SQL procedure successfully completed. I have tried but I didn't get satisfactory answer. Can anybody please help..?
The easiest query I can write for such scope is something like:
SELECT *
FROM <table>
WHERE UPPER(column1) LIKE UPPER('%' || :val || '%')
OR UPPER(column2) LIKE UPPER('%' || :val || '%')
OR UPPER(column3) LIKE UPPER('%' || :val || '%')
OR UPPER(column4) LIKE UPPER('%' || :val || '%');
In this query I search for value :val in all columns of the table using OR conditions, so if at least one column contains the value the row is fetched
If you have many columns you can write a query that builds the final query for you, like the following:
SELECT 'SELECT * FROM <table> WHERE ' || LISTAGG(column_name || ' LIKE ''%' || :val || '%''', ' OR ') WITHIN GROUP (ORDER BY column_name)
FROM dba_tab_columns
WHERE table_name = '<table>'
The result of this query is the query to execute. Note that Oracle has a limit of 4000 characters for a string field built in a query. If your where condition is too big the query will fail.
In this case, the only alternative is to write a stored procedure that builds the query and returns it in a CLOB variable, here's an example:
CREATE OR REPLACE FUNCTION build_query(in_table_name IN VARCHAR2, in_search IN VARCHAR2) RETURN `CLOB` IS
lc_query CLOB := 'SELECT * FROM ' || in_table_name || ' WHERE 1=0';
BEGIN
FOR c IN (
SELECT *
FROM user_tab_columns
WHERE table_name = in_table_name
ORDER BY column_name
) LOOP
lc_query := lc_query || ' OR ' || c.column_name || ' LIKE ''%' || in_search || '%''';
END LOOP;
RETURN lc_query;
END;
This function will works and generates strings longer than 4000 characters.

Resources