I tried to to see what tables are implemented in Oracle SQL Developer when I clicked "+" on the left hand side the window with this error has been shown, before I run this code:
BEGIN
FOR cur_rec IN (SELECT object_name, object_type
FROM user_objects
WHERE object_type IN
('TABLE',
'VIEW',
'PACKAGE',
'PROCEDURE',
'FUNCTION',
'SEQUENCE'
))
LOOP
BEGIN
IF cur_rec.object_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '" CASCADE CONSTRAINTS';
ELSE
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"';
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ( 'FAILED: DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"'
);
END;
END LOOP;
END;
SQL Developer stopped working, and I closed it, and when I run it again this error has been shown.
Thanks for any solutions.
Related
I've got an ETL script which changes the column types of a table to desired type and updates the data. The script works perfectly but I was wondering if there was a better & quicker way of doing it? Working in Redshift.
Current procedure;
CREATE or REPLACE PROCEDURE p_alter_staging_tbls() AS $$
DECLARE
row RECORD;
BEGIN
FOR row IN select * from
(
select distinct table_name, column_name,data_type from staging.staging_col_info_v a order by a.table_name asc
)
loop
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'ADD COLUMN ' || concat('new_',row.column_name) || ' ' || row.data_type ;
EXECUTE 'UPDATE staging.' || row.table_name || ' ' || 'SET ' || concat('new_',row.column_name) || ' ' || '=' || ' ' || row.column_name || '::' || row.data_type ;
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'DROP COLUMN ' || row.column_name ;
execute 'ALTER TABLE staging.' || row.table_name || ' ' || 'RENAME COLUMN '|| concat('new_',row.column_name) || ' ' || 'TO ' || row.column_name;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
For optimization, you can check if the data type needs to be changed or if you already have the correct type and size.
For this purpose you can use a query like this:
SELECT table_schema, table_name, column_name, data_type,
column_default, character_maximum_length, numeric_precision
FROM information_schema.columns
WHERE table_schema = 'staging'
AND table_name = row.table_name
AND column_name = row.column_name
and then check if "data_type" AND "numeric_precision" is different, in this case you can alter the column.
You can also consider to not create a new column, but you can use:
ALTER TABLE table_name
ALTER COLUMN column_name [SET DATA] TYPE new_data_type;
instead of:
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'ADD COLUMN ' || concat('new_',row.column_name) || ' ' || row.data_type ;
EXECUTE 'UPDATE staging.' || row.table_name || ' ' || 'SET ' || concat('new_',row.column_name) || ' ' || '=' || ' ' || row.column_name || '::' || row.data_type ;
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'DROP COLUMN ' || row.column_name ;
execute 'ALTER TABLE staging.' || row.table_name || ' ' || 'RENAME COLUMN '|| concat('new_',row.column_name) || ' ' || 'TO ' || row.column_name;
you can use this:
EXECUTE 'ALTER TABLE staging.' || row.table_name || ' ' || 'ALTER COLUMN '|| row.column_name || ' ' || 'TYPE ' || || row.data_type;
I am using the code below which outputs as intended:
DECLARE
v_ins_param VARCHAR2(10);
CURSOR c_ins_param IS
SELECT status
FROM v$instance;
BEGIN
OPEN c_ins_param;
LOOP
FETCH c_ins_param INTO v_ins_param;
EXIT WHEN c_ins_param%NOTFOUND;
--
--
--
IF v_ins_param = 'OPEN' THEN
DBMS_OUTPUT.PUT_LINE('
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
Great! Your database is up.
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || ' ');
ELSIF v_ins_param = 'MOUNTED' THEN
DBMS_OUTPUT.PUT_LINE('
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
Database is only mounted.
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
');
ELSE
DBMS_OUTPUT.PUT_LINE('
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
Database is neither mounted or open.
' || CHR(35) || '' || CHR(35) ||'' || CHR(35) || '
');
END IF;
END LOOP;
CLOSE c_ins_param;
END;
/
This is the "kind" of output it'll give you:
###
Great! Your database is up.
###
Ultimately this will be a series of anonymous block "typed" scripts like this one which I want to output to a single file.
I am now trying to get the output to just give the text information only, in a html output. I saw this on another page and adapted it for my code to see how it would / could work:
spool c:mag.html
DECLARE
CURSOR c1 IS
SELECT * FROM dept;
BEGIN
DBMS_OUTPUT.PUT_LINE('< pre >');
DBMS_OUTPUT.PUT_LINE('< h1 >Report on Databases</h1>');
FOR mag IN c1
LOOP
EXIT WHEN c1%notfound;
DBMS_OUTPUT.PUT_LINE('< b >Department Name[/b] =' || mag.dname);
END LOOP;
END;
/
However the way of doing this, using:
mag.dname
is not applicable in my 'non for loop' example.
I feel like there must be a more appropriate way of achieving the output. I have tried:
set markup html on
And it does not just returned impact the output but ALL of the code.
Has anyone tried this before and know perhaps how I might get the html output for the returned data only?
Here's an example - I store the following in a script called (say) scr.sql
set termout off
set feedback off
set serverout on
begin
for i in (
select
case
when status = 'OPEN' then '<p>Database is open</p>'
when status = 'MOUNTED' then '<p>Database is mounted</p>'
else '<p>Database is not happy</p>'
end status_output
from v$instance
)
loop
dbms_output.put_line(i.status_output);
end loop;
end;
.
spool /tmp/status.html
/
spool off
and then run this from SQLPlus as
SQL> #scr.sql
and the only thing my resultant status.html is
<p>Database is open</p>
I have a varchar2 with an INSERT and I want to execute it in a procedure I try to do it with an execute but this happens:
EXECUTE IMMEDIATE sql_str;
Error:
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at "SYS.INSERT_MOVIMIENTOS", line 47
ORA-06512: at line 1
Varchar2 carries an insert that is this and works if I paste it but when executing it in the procedure something of the procedure fails.
INSERT INTO MOVIMIENTOS (COD_BANCO, COD_SUCUR, NUM_CTA, FECHA_MOV, TIPO_MOV, IMPORTE) VALUES (2000, 2000, 0, '11/11/08', 'I', 500);
My procedure
CREATE OR REPLACE PROCEDURE INSERT_MOVIMIENTOS (
INSERTMOV_COD_BANCO IN NUMBER,
INSERTMOV_COD_SUCUR IN NUMBER,
INSERTMOV_NUM_CTA IN NUMBER,
INSERTMOV_FECHA_MOV IN DATE,
INSERTMOV_TIPO_MOV IN CHAR,
INSERTMOV_IMPORTE IN NUMBER
)
IS
sql_str VARCHAR2(500) := 'INSERT INTO MOVIMIENTOS (';
movimiento movimientos_typ;
BEGIN
movimiento := movimientos_typ(
INSERTMOV_COD_BANCO,
INSERTMOV_COD_SUCUR,
INSERTMOV_NUM_CTA,
INSERTMOV_FECHA_MOV,
INSERTMOV_TIPO_MOV,
INSERTMOV_IMPORTE
);
IF movimiento.getCOD_BANCO() != 0 THEN
sql_str := sql_str || 'COD_BANCO, COD_SUCUR, NUM_CTA, FECHA_MOV, TIPO_MOV, IMPORTE) VALUES (' ||
movimiento.getCOD_BANCO() || ', ' ||
movimiento.getCOD_SUCUR() || ', ' ||
movimiento.getNUM_CTA() || ', ''' ||
movimiento.getFECHA_MOV() || ''', ''' ||
movimiento.getTIPO_MOV() || ''', ' ||
movimiento.getIMPORTE() || ');';
ELSE
sql_str := sql_str || 'COD_SUCUR, NUM_CTA, FECHA_MOV, TIPO_MOV, IMPORTE) VALUES (' ||
movimiento.getCOD_SUCUR() || ', ' ||
movimiento.getNUM_CTA() || ', ''' ||
movimiento.getFECHA_MOV() || ''', ''' ||
movimiento.getTIPO_MOV() || ''', ' ||
movimiento.getIMPORTE() || ');';
END IF;
DBMS_OUTPUT.PUT_LINE('////////////////////////////////////////');
DBMS_OUTPUT.PUT_LINE('CONSULTA: ' || sql_str);
DBMS_OUTPUT.PUT_LINE('////////////////////////////////////////');
DBMS_OUTPUT.PUT_LINE('DATOS INTRODUCIDOS: ');
movimiento.display;
DBMS_OUTPUT.PUT_LINE('////////////////////////////////////////');
EXECUTE IMMEDIATE sql_str;
DBMS_OUTPUT.PUT_LINE('FUNCION REALIZADA CON EXITO');
END;
/
Donot end with the semicolon ; in your query string.
movimiento.getIMPORTE() || ')';
The error is just because of it.
by the way, you should be using bind variables. Dynamically constructing the values this way is vulnerable to SQL Injection.
I know this is a duplicate question, but I couldn't find a way to reopen the discussion. Im trying to create a stored proc that will search all columns in all tables for a value. This is what I created so far:
CLEAR SCREEN
SET VERIFY OFF
ACCEPT val CHAR PROMPT 'What value do you want to search for: '
CLEAR SCREEN;
DECLARE
match_count integer;
v_search_string varchar2(4000) := <<val>>;
BEGIN
FOR t IN (SELECT owner,
table_name,
column_name
FROM all_tab_columns
WHERE data_type in ('CHAR', 'VARCHAR2', 'NCHAR', 'NVARCHAR2',
'CLOB', 'NCLOB') )
LOOP
BEGIN
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.owner || '.' || t.table_name||
' WHERE '||t.column_name||' = :1'
INTO match_count
USING v_search_string;
IF match_count > 0 THEN
dbms_output.put_line( t.owner || '.' || t.table_name ||' '||t.column_name||' '||match_count );
END IF;
EXCEPTION
WHEN others THEN
dbms_output.put_line( 'Error encountered trying to read ' ||
t.column_name || ' from ' ||
t.owner || '.' || t.table_name );
END;
END LOOP;
END;
/
but I get errors. Any help would be highly appreciated!!
See the comments:
CLEAR SCREEN
SET VERIFY OFF
ACCEPT val CHAR PROMPT 'What value do you want to search for: '
CLEAR SCREEN;
DECLARE
match_count INTEGER;
v_search_string VARCHAR2(4000) := '&val'; /* this was <<val>> */
BEGIN
FOR t IN (SELECT owner,
table_name,
column_name
FROM all_tab_columns
WHERE data_type IN ('CHAR',
'VARCHAR2',
'NCHAR',
'NVARCHAR2',
'CLOB',
'NCLOB'))
LOOP
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || t.owner || '.' || t.table_name || ' WHERE ' || t.column_name || ' = :1' INTO match_count USING v_search_string;
IF match_count > 0
THEN
DBMS_OUTPUT.put_line(t.owner || '.' || t.table_name || ' ' || t.column_name || ' ' || match_count);
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line('Error encountered trying to read ' || t.column_name || ' from ' || t.owner || '.' || t.table_name);
END;
END LOOP;
END;
/
I need regex to capture full "create procedure" statement.
Here is one of examples, which I used for testing my regex:
CREATE OR REPLACE PROCEDURE sp_for_comp (P_VARNAME IN VARCHAR2, P_VALUE IN OUT NUMBER)
as
v_if_exists NUMBER(10,0);
BEGIN
SELECT COUNT(*) INTO v_if_exists FROM PKG_VAR WHERE VARIABLENAME = P_VARNAME;
IF v_if_exists > 0
THEN
begin
SELECT VALUE INTO P_VALUE FROM PKG_VAR WHERE VARIABLENAME = P_VARNAME;
EXCEPTION
WHEN OTHERS THEN
NULL;
end;
ELSE
begin
INSERT INTO PKG_VAR VALUES(P_VARNAME, P_VALUE);
EXCEPTION
WHEN OTHERS THEN
NULL;
end;
END IF;
END;
/
Current regex:
/CREATE\s+(OR\s+REPLACE\s+)?PROCEDURE\s+(\w+)\s*\(((?!.*\bEND\b\s*(\w+\s*)?\;\s*\/).*\s*)+.+/
As for my issue: I use QRegularExpression class and program failed when I run it on large files. Also, when I run it on small file - all works correctly.
After a lot of tests on online debuggers, like regexr.com, I could not find problem in regex.
How I should change it and where are may be problems?
Try something very simple like:
CREATE(\s+OR\s+REPLACE)\s+PROCEDURE.*?END;\s*/
It just looks for the CREATE OR REPLACE PROCEDURE at the start and then the end will be END; followed by / (indicating the end of the PL/SQL block in the SQL scope) on the next line with the minimal amount between.
(Note: You will probably want to use the ni regular expression match parameters to allow . to match the newline character and to do case-insensitive matches.)
Example:
CREATE TABLE script (value ) AS
SELECT 'CREATE OR REPLACE PROCEDURE sp_for_comp (P_VARNAME IN VARCHAR2, P_VALUE IN OUT NUMBER)' || CHR(10)
|| ' as' || CHR(10)
|| ' v_if_exists NUMBER(10,0);' || CHR(10)
|| 'BEGIN' || CHR(10)
|| ' SELECT COUNT(*) INTO v_if_exists FROM PKG_VAR WHERE VARIABLENAME = P_VARNAME;' || CHR(10)
|| ' IF v_if_exists > 0' || CHR(10)
|| ' THEN' || CHR(10)
|| ' begin' || CHR(10)
|| ' SELECT VALUE INTO P_VALUE FROM PKG_VAR WHERE VARIABLENAME = P_VARNAME;' || CHR(10)
|| ' EXCEPTION' || CHR(10)
|| ' WHEN OTHERS THEN' || CHR(10)
|| ' NULL;' || CHR(10)
|| ' end;' || CHR(10)
|| 'ELSE' || CHR(10)
|| ' begin' || CHR(10)
|| ' INSERT INTO PKG_VAR VALUES(P_VARNAME, P_VALUE);' || CHR(10)
|| ' EXCEPTION' || CHR(10)
|| ' WHEN OTHERS THEN' || CHR(10)
|| ' NULL;' || CHR(10)
|| ' end;' || CHR(10)
|| ' END IF;' || CHR(10)
|| 'END;' || CHR(10)
|| '/'
FROM DUAL;
SELECT COUNT(*)
FROM script
WHERE REGEXP_LIKE( value, '^CREATE(\s+OR\s+REPLACE)\s+PROCEDURE.*?END;\s*/$', 'n' );
Outputs:
COUNT(*)
--------
1