Skip to Main Content
Ted Struik - Oracle
Home
Ted Struik - Oracle
Search
Site Map
Statistics
Page Errors
Apex
General
Autocomplete
Conditions
Errors
Items used in PL/SQL
Validations
Dynamic Actions
Logs
Version
App-wide Items
Error Handling
Apex Views
Apex Upgrade 4.2 to 5.1
Database Dependencies
Show Source Code
URLs
Authorization
Modal Dialogs
Apex Office Print (AOP)
Apex-Sert
Reports
Checkboxes
Download
Errors
Nowrap Columns
Substitution Strings
Use IR results in pl/sql
Clickable Row
Row Highlight
Translate Filters etc.
Bar Charts
Column Usage
Reset Pagination
Hide IR Actions menu items
Get Classic Report query
Interactive Grid
ORA-20987
ERR-1002
Copying Text
IG Info
Images & Fonts
Standard Icons & Fonts
WebDav
Font Awesome
Icons/image popup LOV
Lists
Hierarchy
LOVs
Definition Bug
Set 1-item LOV to Disabled
With Clause Errors
Modal LOV Plugin
HTML / CSS / JavaScript
Vertical Align
Legend CSS
Geolocation
Apex.confirm
Pie Charts
Codemirror
Theme Roller
Catching Key Strokes
Browser Cache
Locale
RequireJS
Collapsible Regions
Find JavaScript
Import / Export
Dynamic Translations
Translated Pages
APEXExport (java)
apex_export (pl/sql)
Component Settings
Charts
Translate Charts
[Reports] Bar Charts
Shuttles
Shuttle Sorting
Disable Shuttle Items
Menus
Accordion-Like
Scroll bug
Authorization
Session State
About Session State
Rollback & Commit
Performance of v()
Apex Clone Session
Request
Collections
ORA-20101 & ORA-20104
ORA-00001
Max Row Count
(PL)SQL
External Tables
SQL Plus
Conditions
Long
ORDImage
Date & Timestamp
CGI environment
Sys_context
Rounding percentages
Apex_string.split in SQL
Dbms_metadata
Instr
Regular Expressions
Rollback to Savepoint
Use table aliases
(Pipelined) Bulk Collect
JSON
Source Code Search (PL/SQL)
Source Code Search (SQL)
Format Models
Pipelined Table Functions
Hint no_unnest
Listagg
DBA
Backup & Restore
Users
Export & Import
DBMS Jobs
Tablespaces
Table Size
Flush cache
Access Control List (ACL)
Locks
Java
Constraints
Object Dependencies
Package Dependencies 1
Package Dependencies 2
Grants
SQL History
Startup Errors
ORDS
Miscellaneous
Holidays
E-mail
NLExtract
Windows
VPN
VMware
Links
Google
Visualization Orgchart
Hide Search Results
Reverse Proxy
To-do List
Cytoscape
Graphics
Upscaling
Amazon Prices
Domoticz
DDoS
Hobbies
Motorcycles
'95 Kawasaki ZZR 600
'94 Kawasaki ZZR 1100
'91 Honda CBR 600 F2
'95 Kawasaki ZZR 1100
'99 Honda CBR 1100 XX
'00 Honda CBR 1100 XX
'02 Kawasaki ZX-12R (NL)
'05 Ducati 999 (NL)
'08 Honda Fireblade
'07 Suzuki Bandit 1250A
'18 Suzuki GSX-S 1000 F
MotoGP
Garfield
Lyrics
Skydive
Woodworking
Pantorouter
16 inch Bandsaw
Introduction
Frame
Wheels
Wheel mounts
Blade guides
Trunions and table
Enclosure
Alignment and more
Box Joint Jig
Foldable Sawhorses
Strip Sander XL
Photography
Sony RX10 IV
Search For
Info
Sometimes a pure SQL query to search in source code is easier to use than using a pl/sql solution, like the one shown on my
Source Code Search (PL/SQL)
page.
The query below searches for 1 or more search terms, in both source (packages etc.), views, materialized view, jobs, and synonyms.
Thanks to Arnoud for his contributions.
Things to note:
To get some performance I used a materialize hint for user_source. It speeds it up a lot when using multiple search terms, but I'm still not quite sure why...
The query uses "like", so you have some form of wildcards to play with. Regular expressions would make this even more flexible, but I think that would slow things down too much in most cases..
The line "lower( dbms_xmlgen.convert(xmltype(dbms_metadata.get_xml('VIEW', v.view_name)).extract('//ROWSET/ROW/VIEW_T/TEXT/text()').getclobval(), 1) )" looks quite weird, but it was the fastest way I could find to get the source of (large) views. Life would be a lot easier if user_views would just return a clob instead of a long...
I use apex_string.split for the views, so I am able to use "like" (which only works for varchar2, not clob), and so I can display actual line numbers. And the performance is better than expected.
The "alternative" query is quite nice I think. For example, if you only need to find calls to a function were two specific parameters are used (and not just one of them), this can come in handy.
If you want to change this query for all users instead of just the current user, you will need to make some changes:
Make sure the schema that will run the query has access to all objects. SYS or SYSTEM should be fine of course, but otherwise you may need to grant the SELECT_CATALOG_ROLE role to the user.
This is the reason why I kept this query limited to the user itself; usually you will not have access to all objects, and then you will get errors like this: ORA-31603: object "USER_TAB_COLS_V$" of type VIEW not found in schema "SYS".
Change all references to user_* views to all_* views.
Include the owner column in all (sub)queries.
And make sure to pass the owner into the schema parameter of the dbms_metadata.get_xml calls.
Query
with iv_s as (select distinct lower(column_value) as s from table(apex_string.split('ted_amazon:distinct' ,':')) -- ) -- , -- Source -- Supported types: FUNCTION, JAVA SOURCE, LIBRARY, PACKAGE, PACKAGE BODY, PROCEDURE, TRIGGER, TYPE, TYPE BODY iv_source as (select /*+ materialize */ -- The materialize hint makes this a lot faster, especially when iv_s returns multiple rows. src.name ,src.type ,src.line ,src.text from user_source src where not exists (select 1 -- prevent false positives in wrapped code from user_source sr1 where sr1.name = src.name and sr1.type = src.type and sr1.type in ('FUNCTION' ,'LIBRARY' ,'PACKAGE' ,'PACKAGE BODY' ,'PROCEDURE' ,'TYPE' ,'TYPE BODY') and sr1.line = 1 and instr(sr1.text ,'wrapped') > 0) -- ) -- , -- Views -- Supported types: VIEW, MATERIALIZED_VIEW iv_views_c as ( select vw.view_name as name ,'VIEW' as type ,(case when vw.text_length <= 4000 then to_clob(vw.text_vc) else -- text_vc is a varchar2 column, so dbms_metadata.get_xml is needed when the text_length > 4000 dbms_xmlgen.convert(xmltype(dbms_metadata.get_xml(object_type => 'VIEW', name => vw.view_name)).extract('//ROWSET/ROW/VIEW_T/TEXT/text()').getclobval() ,1) end) as text_clob from user_views vw -- union all select mvw.mview_name as name ,'MATERIALIZED_VIEW' as type ,dbms_xmlgen.convert(xmltype(dbms_metadata.get_xml(object_type => 'MATERIALIZED_VIEW', name => mvw.mview_name)).extract('//ROWSET/ROW/M_VIEW_T/MVIEW/QUERY_TXT/text()').getclobval() ,1) as text_clob from user_mviews mvw -- ) -- , -- Views as lines of text iv_views_l as (select iv_views_c.name ,iv_views_c.type ,row_number() over(partition by iv_views_c.name order by rownum) as line ,t.column_value as text from iv_views_c cross join table(apex_string.split(iv_views_c.text_clob, chr(10))) t -- ) -- , -- Jobs iv_jobs as (select sj.job_name as name ,'JOB - ' || sj.job_type as type ,null as line ,sj.job_action as text from user_scheduler_jobs sj where sj.job_type is not null union all select sp.program_name as name ,'PROGRAM - ' || sp.program_type as type ,null as line ,sp.program_action as text from user_scheduler_programs sp -- union all select to_char(jb.job) as name ,'JOB' as type ,null as line ,jb.what as text from user_jobs jb -- ) -- , -- Synonyms iv_synonyms as (select synonym_name as name ,'SYNONYM' as type ,null as line ,table_name as text from user_synonyms -- ) -- , -- All matches iv_all as ( -- Source select iv_source.* ,iv_s.s from iv_source cross join iv_s where lower(iv_source.text) like '%' || iv_s.s || '%' union all -- Views select iv_views_l.* ,iv_s.s from iv_views_l cross join iv_s where lower(iv_views_l.text) like '%' || iv_s.s || '%' -- union all -- Jobs select iv_jobs.* ,iv_s.s from iv_jobs cross join iv_s where lower(iv_jobs.text) like '%' || iv_s.s || '%' union all -- Synonyms select iv_synonyms.* ,iv_s.s from iv_synonyms cross join iv_s where lower(iv_synonyms.text) like '%' || iv_s.s || '%' -- ) -- Simple query: find all matches of all search terms select iv_all.* from iv_all order by 1 ,2 ,3 /* -- Alternative query: find "related" matches of different search terms, within x lines of each other select iv_all.* ,iv_all_2.line ,iv_all_2.text from iv_all join iv_all iv_all_2 on (iv_all_2.name = iv_all.name -- and iv_all_2.type = iv_all.type -- and iv_all_2.line - iv_all.line between 1 and 10 -- ) where lower(iv_all.text) like '%searchterm1%' and lower(iv_all_2.text) like '%searchterm2%' order by 1 ,2 ,3 ,iv_all_2.line */