I have a table with several columns, and I would like to eliminate spaces value (' ') from the values. The query is:
update table
set column_name = trim(both ' ' from column_name)
where column_name like '% '
and since the table contains around 55 columns so probably a loop would be a feasible idea instead of writing update statement for each and every column.
First I checked if looping is working:
declare
column_name varchar2(2048);
cursor pointer is
select column_name into column_name from user_tab_cols where table_name = 'TABLE_NAME';
begin
for x in pointer
loop
dbms_output.put_line(x.column_name);
end loop;
end;
yes, it is working. I get column names in dbms_output window.
Now,
Here is what I am trying to do which doesn't seem to work:
declare
column_var varchar2(2048);
cursor pointer is
select column_name into column_var from user_tab_cols where table_name = 'TABLE_NAME';
begin
for x in pointer
loop
update table_name
set x.column_var = trim(both ' ' from x.column_var)
where x.column_var like '% ';
commit;
end loop;
end;
This is, unfortunately not working. This is error I get:
ORA-06550: line 11, column 18:
PLS-00302: component 'COLUMN_VAR' must be declared.
ORA-06550: line 11, column 16:
PL/SQL: ORA-00904: "X"."COLUMN_VAR": invalid identifier
ORA-06550: line 9, column 10:
PL/SQL: SQL Statement ignored
Any idea where I am going off the track?
Thanks in advance :-)
I think you need to provide the actual column name, rather than the string representing the column name in the statement. Would an execute immediate work for you?
declare
column_var varchar2(2048);
cursor pointer is
select column_name into column_var from user_tab_cols where table_name = 'TABLE_NAME';
begin
for x in pointer
loop
execute immediate
'update table_name ' ||
'set '|| x.column_var ||' = trim(both '' '' from '|| x.column_var ||')'||
'where '|| x.column_var ||' like ''% ''';
commit;
end loop;
end;
You need to use dynamic sql for this
BEGIN
FOR t IN (select column_name from user_tab_cols where table_name = 'MyTable')
LOOP
EXECUTE IMMEDIATE
'update MyTable set '||t.column_name||' = trim(both '' '' from '||t.column_name||') where '||t.column_name||' like ''% ''';
END LOOP;
END;
/
Related
I want to do select column_name from table_name where column_name.
table_name should be coming from cursor.
Query:
DECLARE
COLUMN_NAME VARCHAR(50);
TABLE_NAME VARCHAR(100);
schema_name VARCHAR(100);
A VARCHAR(100);
B VARCHAR(100);
CURSOR col_cursor IS
select col.owner as schema_name,
col.table_name,
col.column_name
from sys.all_tab_columns col
inner join sys.all_tables t
on col.owner = t.owner and
col.table_name = t.table_name
where col.owner = 'PIYUSH1910_BEFORE'
AND
DATA_TYPE = 'NUMBER'
AND
DATA_PRECISION IS NULL
AND
col.TABLE_NAME NOT LIKE '%ER%';
BEGIN
OPEN col_cursor;
LOOP
FETCH col_cursor INTO schema_name,TABLE_NAME,COLUMN_NAME;
EXIT WHEN col_cursor%NOTFOUND;
EXECUTE IMMEDIATE ' SELECT '||COLUMN_NAME ||' INTO A from ' || Table_Name || 'WHERE'||COLUMN_NAME||'- TRUNC('||COLUMN_NAME||',2) > 0';
dbms_output.Put_line(A);
END LOOP;
CLOSE col_cursor;
END
But its throwing this error:
Error report - ORA-00933: SQL command not properly ended. ORA-06512: at line 29 00933. 00000 - "SQL command not properly ended *Cause: *Action:
INTO clause must be at the end while using the EXECUTE IMMEDIATE as follows:
EXECUTE IMMEDIATE ' SELECT '||COLUMN_NAME ||' from '
|| Table_Name || ' WHERE '||COLUMN_NAME||'- TRUNC('||COLUMN_NAME||',2) > 0'
INTO A;
Also, space before and after WHERE keyword is added in the above solution.
Change your EXECUTE IMMEDIATE to:
EXECUTE IMMEDIATE ' SELECT '|| COLUMN_NAME || ' from ' || Table_Name ||
' WHERE ' || COLUMN_NAME || '- TRUNC('||COLUMN_NAME||',2) > 0'
INTO A;
This moves the INTO clause to the correct position (in this case it's part of the EXECUTE IMMEDIATE rather than being part of the SELECT) and reformats the code slightly so that column names are separated from e.g. the WHERE keyword.
I have problem about how to get all of list structure table using loop pl/sql,
i have syntax loop like bellow :
BEGIN
FOR x IN (SELECT table_name FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'DESC' || x.table_name;
END LOOP;
COMMIT;
END;
and this is log output from sql developer
Error starting at line 14 in command:
BEGIN
FOR x IN (SELECT table_name FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'DESC' || x.table_name;
END LOOP;
COMMIT;
END;
Error report:
ORA-00900: invalid SQL statement
ORA-06512: at line 4
00900. 00000 - "invalid SQL statement"
*Cause:
*Action:
Help me to solve this
Thanks
The DESC command is neither SQL nor plsql but a sqlplus command, so you can't use it in a plsql code.
More than that, why ? you can get all the values you need from USER_TAB_COLUMNS ...
Use DBMS_OUTPUT.put_line() instead:
BEGIN
FOR x IN (SELECT COLUMN_NAME, DATA_TYPE, NULLABLE FROM USER_TAB_COLUMNS)
LOOP
DBMS_OUTPUT.put_line(COLUMN_NAME || ' ' || DATA_TYPE || ' ' || NULLABLE );
END LOOP;
COMMIT;
END;
Of course this can be formatted nicer and there are more columns you can select ...
Consider this instead:
Select * from All_tab_Cols
or to be closer to what is returned from describe:
Select Owner, Table_name, ColumN_Name, Data_Type, Data_Length, Nullable
from all_tab_Cols;
To address your specific problem shouldn't it be:
EXECUTE IMMEDIATE 'DESC ' || x.table_name|| ';';
Missing space between desc & table name and ; is part of the SQL to run isn't it?
If you're trying to reverse engineer the schema then use the DBMS_Metadata package to do so, as it can also extract constraints, privileges, users etc.
I want to the the number of records in all tables that match a specific name criteria. Here is the SQL I built
Declare SQLStatement VARCHAR (8000) :='';
BEGIN
SELECT 'SELECT COUNT (*) FROM ' || Table_Name || ';'
INTO SQLStatement
FROM All_Tables
WHERE 1=1
AND UPPER (Table_Name) LIKE UPPER ('MSRS%');
IF SQLStatement <> '' THEN
EXECUTE IMMEDIATE SQLStatement;
END IF;
END;
/
But I get the following error:
Error at line 1
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 3
Script Terminated on line 1.
How do I modify this so that it runs for all matching tables?
Update:
Based on an answer received, I tried the following but I do not get anything in the DBMS_OUTPUT
declare
cnt number;
begin
for r in (select table_name from all_tables) loop
dbms_output.put_line('select count(*) from CDR.' || r.table_name);
end loop;
end;
/
declare
cnt number;
begin
for r in (select owner, table_name from all_tables
where upper(table_name) like ('%MSRS%')) loop
execute immediate 'select count(*) from "'
|| r.owner || '"."'
|| r.table_name || '"'
into cnt;
dbms_output.put_line(r.owner || '.' || r.table_name || ': ' || cnt);
end loop;
end;
/
If you're selecting from all_tables you cannot count on having been given the grants necessary to select from the table name. You should therefore check for the ORA-00942: table or view does not exist error thrown.
As to the cause for your error: You get this error because the select statement returns a result set with more than one row (one for each table) and you cannot assign such a result set to a varchar2.
By the way, make sure you enable dbms_output with SET SERVEROUT ON before executing this block.
In Oracle 10g, is there a way to do the following in PL/SQL?
for each table in database
for each row in table
for each column in row
if column is of type 'varchar2'
column = trim(column)
Thanks!
Of course, doing large-scale dynamic updates is potentially dangerous and time-consuming. But here's how you can generate the commands you want. This is for a single schema, and will just build the commands and output them. You could copy them into a script and review them before running. Or, you could change dbms_output.put_line( ... ) to EXECUTE IMMEDIATE ... to have this script execute all the statements as they are generated.
SET SERVEROUTPUT ON
BEGIN
FOR c IN
(SELECT t.table_name, c.column_name
FROM user_tables t, user_tab_columns c
WHERE c.table_name = t.table_name
AND data_type='VARCHAR2')
LOOP
dbms_output.put_line(
'UPDATE '||c.table_name||
' SET '||c.column_name||' = TRIM('||c.column_name||') WHERE '||
c.column_name||' <> TRIM('||c.column_name||') OR ('||
c.column_name||' IS NOT NULL AND TRIM('||c.column_name||') IS NULL)'
);
END LOOP;
END;
Presumably you want to do this for every column in a schema, not in the database. Trying to do this to the dictionary tables would be a bad idea...
declare
v_schema varchar2(30) := 'YOUR_SCHEMA_NAME';
cursor cur_tables (p_schema_name varchar2) is
select owner, table_name, column_name
from all_tables at,
inner join all_tab_columns atc
on at.owner = atc.owner
and at.table_name = atc.table_name
where atc.data_type = 'VARCHAR2'
and at.owner = p_schema;
begin
for r_table in cur_tables loop
execute immediate 'update ' || r.owner || '.' || r.table_name
|| ' set ' || r.column_name || ' = trim(' || r.column_name ||');';
end loop;
end;
This will only work for fields that are VARCHAR2s in the first place. If your database contains CHAR fields, then you're out of luck, because CHAR fields are always padded to their maximum length.
This is a noobie question, most likely syntax one. But I am kinda lost...
I need to go over all columns in all tables in Oracle to generate trigger script. That trigger should insert the row being updated to a log table which is nearly the same as the original table. I thought I would just go over all the columns and just concatenate strings. Fairly easy but I am struggling with the syntax...
Here's what I have so far:
DECLARE
cursor tableNames is
select table_name
from user_tables
where table_name not like '%_A';
lSql varchar2(3000);
type t_columnRow is ref cursor;
v_columns t_columnRow;
begin
FOR tableName in tableNames
LOOP
open v_columns for select COLUMN_NAME from user_tab_columns where table_name = tableName;
for columnRow in v_columns LOOP
DBMS_OUTPUT.PUT_LINE(tableName || '.' || columnRow.COLUMN_NAME);
-- Here I would just concatenate the strings ....
END LOOP;
END LOOP;
End;
For that I am getting the following error:
Error at line 1
ORA-06550: line 14, column 84:
PLS-00382: expression is of wrong type
ORA-06550: line 16, column 22:
PLS-00221: 'V_COLUMNS' is not a procedure or is undefined
ORA-06550: line 16, column 5:
PL/SQL: Statement ignored
Try this:
BEGIN
FOR t IN (SELECT table_name FROM user_tables WHERE table_name not like '%_A')
LOOP
FOR c IN (SELECT column_name FROM user_tab_columns WHERE table_name = t.table_name)
LOOP
DBMS_OUTPUT.PUT_LINE(t.table_name||'.'||c.column_name);
-- Here I would just concatenate the strings ....
END LOOP;
END LOOP;
END;
You may be able to get away with something as simple as this:
DECLARE
cursor tableNames is
select table_name
from user_tables
where table_name not like '%_A';
lSql varchar2(3000);
begin
FOR tableName in tableNames
LOOP
for columnRow in (select COLUMN_NAME from user_tab_columns where table_name = tableName) LOOP
DBMS_OUTPUT.PUT_LINE(tableName || '.' || columnRow.COLUMN_NAME);
-- Here I would just concatenate the strings ....
END LOOP;
END LOOP;
End;