More than a question, its an information sharing post.
I have come across a situation today where i needed to look for a sting in the entire database of an application with no idea of, which table/column it belongs to.
Below is a PL/SQL block i wrote and used to help my propose. Hope its helps others to with a similar requirement.
Declare
i NUMBER := 0;
counter_intable NUMBER :=0;
BEGIN
FOR rec IN (
select
'select count(*) ' ||
' from '||table_name||
' where '||column_name||' like''%732-851%'' ' as sql_command
from user_tab_columns
where data_type='VARCHAR2'
)
LOOP
execute immediate rec.sql_command into counter_intable;
IF counter_intable != 0 THEN
i := i + 1;
DBMS_OUTPUT.put_line ('Match found using command ::' || rec.sql_command);
DBMS_OUTPUT.put_line ('count ::' || counter_intable);
END IF;
END LOOP;
DBMS_OUTPUT.put_line ('total commands matched :: ' || i);
END;
replace your string at the place of : 732-851 in the code block
Why PL/SQL? You could do the same in SQL using xmlsequence.
For example, I want to search for the value 'KING' -
SQL> variable val varchar2(10)
SQL> exec :val := 'KING'
PL/SQL procedure successfully completed.
SQL> SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword",
2 SUBSTR (table_name, 1, 14) "Table",
3 SUBSTR (column_name, 1, 14) "Column"
4 FROM cols,
5 TABLE (xmlsequence (dbms_xmlgen.getxmltype ('select '
6 || column_name
7 || ' from '
8 || table_name
9 || ' where upper('
10 || column_name
11 || ') like upper(''%'
12 || :val
13 || '%'')' ).extract ('ROWSET/ROW/*') ) ) t
14 ORDER BY "Table"
15 /
Searchword Table Column
----------- -------------- --------------
KING EMP ENAME
SQL>
You could search for any data type values, please read SQL to Search for a VALUE in all COLUMNS of all TABLES in an entire SCHEMA
Related
i am currently stuck on this pl/sql problem, i am trying to gather all the information of a APPLICANT who APPLIES to a certain POSITION (3 different tables) into a stored procedure.
Unfortunately i am very new to oracle and pl/sql so i think my joins may be sloppy aswell as my main problem of dbms_output.put_line is not printing out the data that i need. I figure maybe it is in the wrong place in the code block or there is a problem coming all the way down from my join statements.
enter code here
SET ECHO ON
SET FEEDBACK ON
SET LINESIZE 100
SET PAGESIZE 100
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE APPLICANTS IS
first_name APPLICANT.FNAME%TYPE;
last_name APPLICANT.LNAME%TYPE;
position_number APPLIES.PNUMBER%TYPE;
position_title POSITION.TITLE%TYPE;
str VARCHAR(300);
CURSOR fnameCursor IS
SELECT FNAME
FROM APPLICANT;
BEGIN
FOR fnameCursor IN (SELECT APPLICANT.LNAME, APPLIES.PNUMBER,
POSITION.TITLE INTO last_name, position_number, position_title
FROM APPLICANT JOIN APPLIES ON APPLICANT.ANUMBER =
APPLIES.ANUMBER
JOIN POSITION ON POSITION.PNUMBER = APPLIES.PNUMBER
WHERE FNAME = first_name
ORDER BY LNAME DESC)
LOOP
str := position_number || '' || first_name || '' || last_name || ': ' ||
position_title;
dbms_output.put_line(str);
--EXIT WHEN fnameCursor%NOTFOUND;
END LOOP;
END APPLICANTS;
/
EXECUTE APPLICANTS;
It is surprising to know that the procedure is compiling. You are using an INTO clause inside an implicit cursor query. Also, I believe first_name should come as an argument to your procedure but you have not mentioned it.
More importantly, the columns selected/aliased within the cursor should be referred within the loop using cursor's record variable fnamecursor
CREATE OR REPLACE PROCEDURE APPLICANTS(first_name APPLICANT.FNAME%TYPE)
IS
str VARCHAR(300);
BEGIN
FOR fnamecursor IN (
SELECT applicant.lname as last_name,
applies.pnumber as position_number,
position.title as position_title
FROM applicant
JOIN applies ON applicant.anumber = applies.anumber
JOIN position ON position.pnumber = applies.pnumber
WHERE fname = first_name
ORDER BY lname DESC
) LOOP
str := fnamecursor.position_number || ' ' || first_name || ' ' ||
fnamecursor.last_name || ': ' || fnamecursor.position_title;
dbms_output.put_line(str);
END LOOP;
END applicants;
/
Want to know the best way/approach to stream millions of records from DB table(oracle 11)
I tried simple
stmt.executeQuery() with setFetchSize on stmt, resultset etc. but it did not return any records when table has millions of records
tried with oracle 'rownum' clause, still returns nothing no execption
There are procedures like below
http://www.sqlines.com/postgresql-to-oracle/copy_export_csv_from_procedure
but it needs file package...
My question is there any best approach to stream such millions of records to UI from backend???
like best way to store large(how much) in local storage at browser? this has to secure storage as the data is sensitive?
Please help me with this.
NOTE: ORM/JPA cannot be used as the table generation is dynamic
Thanks!
Well, this is how I have solved it...
step 1 : oracle stored procedure to get the number of 'pages' based on your desired no. of records/page
create or replace
procedure sp_dynlkp_pages (pTable in varchar2, rowCnt out number)
as
begin
EXECUTE IMMEDIATE 'select count(*) from ' || pTable into rowCnt;
end;
step 2 : display the page numbers is drop down and on selection of page number from down fire rest call with input page number
create or replace procedure sp_dynlkp_data_view (pTable in varchar2, pageNumber in number, pageSize in number, p_data_cursor out sys_refcursor)
as
v_sql varchar2(4000);
v_sql1 varchar2(4000);
begin
v_sql := '';
for r in (select column_name from user_tab_cols where table_name = pTable)loop
-- decrypt fn
--v_sql := v_sql || 'f_decrypt(' || r.column_name ||', ' || dKey || ')' || ',';
v_sql := v_sql || r.column_name || ',';
end loop;
v_sql := rtrim(v_sql, ',');-- || ' from ' || pTable; --|| ' where rownum < ' || r_cnt;
v_sql1 := 'SELECT ' || v_sql || ' FROM
(
SELECT a.*, rownum r__
FROM
( select * from '
|| pTable
|| ') a
WHERE rownum < ' || ((pageNumber * pageSize) + 1)
|| ')
WHERE r__ >= ' || (((pageNumber-1) * pageSize) + 1);
--DBMS_OUTPUT.PUT_LINE(v_sql1);
open p_data_cursor for v_sql1;
end;
NOTE: On UI front I am using ng-grid(because of project spec), you guys can use any latest feature rich UI grid component.
I am trying to update all the columns of type NVARCHAR2 to some random string in my database. I iterated through all the columns in the database of type nvarchar2 and executed an update statement for each column.
for i in (
select
table_name,
column_name
from
user_tab_columns
where
data_type = 'NVARCHAR2'
) loop
execute immediate
'update ' || i.table_name || 'set ' || i.column_name ||
' = DBMS_RANDOM.STRING(''X'', length('|| i.column_name ||'))
where ' || i.column_name || ' is not null';
Instead of running an update statement for every column of type nvarchar2, I want to update all the nvarchar columns of a particular table with a single update statement for efficiency(that is, one update statement per 1 table). For this, I tried to bulk collect all the nvarchar columns in a table, into a temporary storage. But, I am stuck at writing a dynamic update statement for this. Could you please help me with this? Thanks in advance!
You can try this one. However, depending on your table it could be not the fastest solution.
for aTable in (
select table_name,
listagg(column_name||' = nvl2('||column_name||', DBMS_RANDOM.STRING(''XX'', length('||column_name||')), NULL)') WITHIN GROUP (ORDER BY column_name) as upd,
listagg(column_name) WITHIN GROUP (ORDER BY column_name) as con
from user_tab_columns
where DATA_TYPE = 'NVARCHAR2'
group by table_name
) loop
execute immediate
'UPDATE '||aTable.table_name ||
' SET '||aTable.upd ||
' WHERE COALESCE('||aTable.con||') IS NOT NULL';
end loop;
Resulting UPDATE (verify with DBMS_OUTPUT.PUT_LINE(..)) should look like this:
UPDATE MY_TABLE SET
COL_A = nvl2(COL_A, DBMS_RANDOM.STRING('XX', length(COL_A)), NULL),
COL_B = nvl2(COL_B, DBMS_RANDOM.STRING('XX', length(COL_B)), NULL)
WHERE COALESCE(COL_A, COL_B) IS NOT NULL;
Please try this:
DECLARE
CURSOR CUR IS
SELECT
TABLE_NAME,
LISTAGG(COLUMN_NAME||' = DBMS_RANDOM.STRING(''X'', length(NVL('||
COLUMN_NAME ||',''A''))',', ')
WITHIN GROUP (ORDER BY COLUMN_ID) COLUMN_NAME
FROM DBA_TAB_COLUMNS
WHERE DATA_TYPE = 'NVARCHAR2'
GROUP BY TABLE_NAME;
TYPE TAB IS TABLE OF CUR%ROWTYPE INDEX BY PLS_INTEGER;
T TAB;
S VARCHAR2(4000);
BEGIN
OPEN CUR;
LOOP
FETCH CUR BULK COLLECT INTO T LIMIT 1000;
EXIT WHEN T.COUNT = 0;
FOR i IN 1..T.COUNT LOOP
S := 'UPDATE ' || T(i).TABLE_NAME || ' SET ' || T(i).COLUMN_NAME;
EXECUTE IMMEDIATE S;
END LOOP;
END LOOP;
COMMIT;
END;
/
I think that would do it. But as I said in the comments, you need to validate the syntax since I don't have an Oracle instance to test it.
for i in (
select table_name,
'update || i.table_name || set ' ||
listagg( column_name || '= NLV( ' || column_name || ', '
|| 'DBMS_RANDOM.STRING(''X'', length('|| column_name ||') ) )'
|| ';'
) WITHIN GROUP (ORDER BY column_name) as updCommand
from user_tab_columns
where DATA_TYPE = 'NVARCHAR2'
group by table_name
) loop
execute immediate i.updCommand;
end loop;
If you find any error, let me know in the comments so I can fix it.
I have a requirement I need your help with.
Number of rows in a table : 130
That is the only data I have. Based on this, Is it possible to find out the table names from an Oracle Database that contain 130 rows in them.
Thanks
Sam
SELECT TABLE_NAME FROM dba_tables WHERE num_rows = 130
-- num_rows = 130 can be replaced with any requirement you have
You can try with some dynamic SQL:
declare
n number;
begin
for t in (
select owner || '.' || table_name as tab
from dba_tables
where owner = 'YOUR_SCHEMA' /* IF YOU KNOW THE SCHEMA */
)
loop
execute immediate 'select count(1) from ' || t.tab into n;
if n = 130 then
dbms_output.put_line('Table ' || t.tab );
end if;
end loop;
end;
Please consider that, depending on the number of tables/records in your DB, this can take very long to run.
I hope this query may help you:
Query 1 : SELECT CONCAT('SELECT COUNT(*) as cnt FROM ', table_name, ' union all') FROM information_schema.tables WHERE table_schema = 'aes';
Query 2: select max(attendance) from ( paste the results obtained from the above query and remove the last union all) as tmptable;
Reference:
Find Table with maximum number of rows in a database in mysql
I need to do a row count on a Netezza system but only where 2 columns have certain values
I have
SELECT TABLENAME, RELTUPLES
FROM _V_TABLE
WHERE objtype = 'TABLE' and tablename like 'MY%STUFF'
This will show me all table names and their row counts
But I need to add a where clause into it. columnA= 1 and columnB = ABC,
every table has these 2 column names in it.
Thanks
Craig
If you want to do this via SQL, then you can accomplish this with a stored procedure. Here's a stored procedure that will do what I think you're asking for.
My assumption is that you want to only count the rows in tables that actually match the column values specified, so RELTUPLES in _v_tables won't be of use for that. The sample stored procedure code also assumes that each of the columns is varchar(1000). You'll have to alter the code if you want to match other datatypes.
Prior to creating the stored procedure, create a reference table like so:
create table reftable_sp_row_count (tablename varchar(1000), rowcount bigint) distribute on random;
Then create the stored procedure like so:
CREATE OR REPLACE PROCEDURE SP_ROW_COUNT(VARCHAR(254), VARCHAR(254), VARCHAR(254), VARCHAR(254), VARCHAR(254))
RETURNS REFTABLE(REFTABLE_SP_ROW_COUNT)
EXECUTE AS OWNER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
pTablePattern ALIAS FOR $1;
pColOneName ALIAS FOR $2;
pColOneValue ALIAS FOR $3;
pColTwoName ALIAS FOR $4;
pcolTwoValue ALIAS FOR $5;
vRecord RECORD;
BEGIN
for vRecord in
EXECUTE 'SELECT schema
|| ''.''
|| tablename tablename
FROM _v_table v
WHERE tablename LIKE ''' || upper(pTablePattern) || '''
AND EXISTS
(
SELECT attname
FROM _v_relation_column c
WHERE c.objid = v.objid
AND attname = ''' || upper(pColOneName) || '''
)
AND EXISTS
(
SELECT attname
FROM _v_relation_column c
WHERE c.objid = v.objid
AND attname = ''' || upper(pColTwoName) || '''
)'
LOOP
EXECUTE IMMEDIATE 'INSERT INTO ' || REFTABLENAME ||
' SELECT ''' || vRecord.tablename || ''' , COUNT(1) from ' || vRecord.tablename ||
' where ' || upper(pColOneName) || ' = ''' || pColOneValue || ''' and ' || upper(pColTwoName) || ' = ''' || pColTwoValue || ''' ;';
-- Note that if you change the data types for a given column to a different type then you'll want to change ''' || pColOneValue || ''' to ' || pColOneValue || ' as appropriate
END LOOP;
RETURN REFTABLE;
END;
END_PROC;
Here is some sample output.
TESTDB.ADMIN(ADMIN)=> select * from table_1 order by colA, colB;
COLA | COLB
------+------
ABC | BLUE
ABC | BLUE
ABC | BLUE
ABC | RED
ABC | RED
(5 rows)
TESTDB.ADMIN(ADMIN)=> select * from table_2 order by colA, colB;
COLA | COLB
------+--------
ABC | BLUE
ABC | BLUE
XYZ | BLUE
XYZ | BLUE
XYZ | YELLOW
(5 rows)
TESTDB.ADMIN(ADMIN)=> call sp_row_count('TABLE_%', 'COLA', 'ABC', 'COLB','BLUE');
TABLENAME | ROWCOUNT
---------------+----------
ADMIN.TABLE_1 | 3
ADMIN.TABLE_2 | 2
(2 rows)