How to create a script that will copy tables from another schema into my schema using PL/SQL advanced scripting in SQLDEV? - sql

So, I'm trying to create a script that will generate SQL codes for copying tables from HR schema into my own schema.
What I got so far is this but it's incorrect... will anyone help me or give me hints?
select 'create table ' || USER_TABLES || '_copy as select * from ' || USER_TABLES || ';'from hr_tables;
Please help me I'm new at this and so desperate.

Try this:
SELECT 'CREATE TABLE ' ||table_name || '_copy AS SELECT * FROM ' || table_name || ';'
FROM all_tables
WHERE OWNER = 'HR';

Related

Big query: Replace string parts in multiple columns dynamically

I have a dynamic table with an indertermined number of columns [statement_nn] with strings. I need to replace string parts by the correspondent item
The table looks like this: Original table
How could I do the operation having in mind that “statement” columns are variable and cannot specifically use them in a standard REPLACE statement?
This is the end result Im looking to get: Desired result
I tried to make an array of "statement" columns and replace items there, but I need to be able to keep column names to get the desired result
You can use EXECUTE IMMEDIATE to dynamically select and replace your desired items. The way I solved it was replacing each placeholder manually with the following query:
execute immediate (
select 'select * replace(' ||
string_agg('regexp_replace(' ||
'regexp_replace(' ||
'regexp_replace(' || column_name || ',' || ' r"<name>", name)'
|| ',' || ' r"<surname>", surname)'
|| ',' || ' r"<registration_year>", CAST(registration_year as STRING))'
|| ' as ' || column_name, ', ') ||
') from project_name.dataset_name.table_name'
from `project_name.dataset_name.INFORMATION_SCHEMA.COLUMNS`
where table_name = 'table_name'
and STARTS_WITH(column_name, "statement_")
)
Remember to replace project_name, dataset_name, and table_name.

Cleaning a SQL schema before using SQL Developer Database copy tool

I have a database for an application and several environment (development, test and production). I would like to use the option Database copy from SQL Developer in order to retrieve data from the production and copy them in development. Thus data on both environments will be the same.
With a previous version of the program all was working perfectly. Nevertheless with a new version (SQL Developer 18.2) imposed by our company, I obtain several error with different objects like sequences, existing table, primary key, ...) during the copy.
Thus I would like to use a script for cleaning the objects of the Database before to use the tool in order to see if the problem will be solved. But I don't know how to do that.
I found and updated this script:
BEGIN
FOR cur_rec IN (SELECT object_name, object_type
FROM user_objects
WHERE object_type IN
('TABLE',
'VIEW',
'PACKAGE',
'PROCEDURE',
'FUNCTION',
'SEQUENCE',
'SYNONYM'
))
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;
Nevertheless this script Cleanup the Schema by DROPPING all objects. I would like to keep the structure and the objects but just empty the conten.
Could you please help me how to do for cleaning the different object without deleting them and importing again?
Thank in advance for your help.
Sebastien

Execute a SQL statement prepared by another SQL

Is it possible to execute a ALTER INDEX prepared by doing a SELECT on sys tables in Oracle 12c. Please see below
I am trying to find the unused indexes for which I have prepared the alter statements by select clause below -
SELECT 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
FROM dba_indexes
WHERE owner NOT in (
'SYSTEM',
'SYS');
Next, I will have to manually copy the output of this SQL to a new SQL commander tab and execute them. Rather is it possible to execute these statements directly instead of showing them?
I am trying to achieve this in SQL only, as a single statement executable from any SQL utility like DBViz or SQL+, and NOT IN PL/SQL or Unix.
You can do this two ways:
1- Spoofing the result to a file and running the file.
set pages 0 lines 200 feed off term off
spool _file
SELECT 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
FROM dba_indexes
WHERE owner NOT in ('SYSTEM','SYS');
spool off
#_file
1- Or via PL/SQL
BEGIN
FOR rec in (select owner, index_name FROM dba_indexes WHERE owner NOT in ('SYSTEM','SYS'))
LOOP
query := 'alter index ' || rec.owner || '.' || rec.index_name || ' monitoring usage'
execute immediate query;
END LOOP;
end;
/
SELECT * FROM(SELECT 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
FROM dba_indexes
WHERE owner NOT in (
'SYSTEM',
'SYS');)

SAP HANA execute query generated within a procedure

I am new with SAP HANA, I am trying to generate a query and execute it within a stored procedure.
I got an error and I am not sure that HANA can do something like that.
Here my code
CREATE PROCEDURE "PROCEDURE_IBA_TESTCSV"(
IN SCHEMA_NAME VARCHAR(100))
LANGUAGE SQLSCRIPT SQL SECURITY INVOKER AS
BEGIN
DECLARE T VARCHAR(1000);
DECLARE TA VARCHAR(1000);
SELECT
' SELECT ' || MAX(C_1) || IFNULL(MAX(C_2),'')|| IFNULL(MAX(C_3),'') ||' AS STATEMENT FROM ' || SCHEMA_NAME || '.' || TABLE_NAME || ' ' INTO T
FROM (
SELECT POSITION, DATA_TYPE_ID, COLUMN_NAME ,SCHEMA_NAME, TABLE_NAME ,
CASE WHEN POSITION = 1 THEN
' CASE WHEN ( '|| COLUMN_NAME ||' IS NULL ) THEN '''' ELSE REPLACE(TO_CHAR(' || COLUMN_NAME || '),''.'','','') END' END AS C_1,
CASE WHEN POSITION = 2 THEN '||''#''|| CASE WHEN ( '|| COLUMN_NAME ||' IS NULL ) THEN '''' ELSE TO_NVARCHAR('||COLUMN_NAME||') END' END AS C_2,
CASE WHEN POSITION = 3 THEN '||''#''|| CASE WHEN ( '|| COLUMN_NAME ||' IS NULL ) THEN '''' ELSE TO_NVARCHAR('||COLUMN_NAME||') END' END AS C_3
FROM (
select SCALE,SCHEMA_NAME,position,TABLE_NAME,column_name, data_type_id from TABLE_COLUMNS where
schema_name ='IMPORT_KT_STAMM_IK_348BA_20160706' AND TABLE_NAME='CLS_220_KTHISTORIE')) group by SCHEMA_NAME,TABLE_NAME;
execute immediate :T ;
INSERT INTO Test SELECT :T from DUMMY;
END;
With execute :T I get this output
I would like to store SUM(length) of this output into a variable within the same procedure.
Is that possible ? Any help ?
thanks in advance
Ok, now I understand, where this is going.
As you want to work with tables of different shape, you won't be able to avoid dynamic SQL altogether.
But since you always melt it into a single column, you could simply store that transformed data into, say a temporary table, and run the SUM(LENGTH(()) on that.
Not sure though why you want to go through this rather painful exercise, instead of simply exporting the data into some folder and checking the resulting size there.
I don't quite get why you use dynamic SQL here. With dynamic SQL (exec/execute immediate) you don't get access to the result set.
Alternatively you can use cursors.
You can provide parameters for SCHEMA_NAME and TABLE_NAME and be 'dynamic' that way.
I guess this question is related to SAP HANA getting csv data size right?
I modified my code:
I write "insert into Table SELECT " instead "SELECT" in line 8
and now I get data in table

How to Refer to a Column by ID or Index Number

In Oracle PL/SQL, I have run a query and am trying to read through each column for each row one by one so I can concatenate them together with a delimiter (hard format requirement). The script is used on multiple tables of varying sizes, so the number of columns is not known in advance. I used
SELECT COUNT(column_name) INTO NumColumns FROM all_tabs_cols
WHERE table_name = Table_Array(i);
where Table_Array has already been defined. This is in the middle of a for loop and has successfully gotten me a total number of columns. Table_Cursor is a SELECT * statement. After this I am trying to do something like
FOR j IN 0..NumColumns-1 LOOP
FETCH TABLE_CURSOR.column(j) INTO DataValue;
DBMS_OUTPUT.PUT(DataValue || '/');
END LOOP
The above is pseudo code. It illustrates the concept I am after. I do not know PL/SQL well enough to know how to get a value like this out of a row. I am also worried about accidentally advancing the cursor while doing this. How can I accomplish this task?
You must use some form of dynamic SQL. Here is a quick example:
It builds the SQL statement that will select the '/' separated columns from the table you want. Then it uses dynamic SQL to run that SQL statement.
DECLARE
p_table_name VARCHAR2(30) := 'DBA_OBJECTS';
l_sql VARCHAR2(32000);
TYPE varchar2tab IS TABLE OF VARCHAR2(32000);
l_array varchar2tab;
BEGIN
SELECT 'SELECT ' || listagg(column_name,' ||''/''||') within group ( order by column_id ) || ' FROM ' || owner || '.' || table_name || ' WHERE ROWNUM <= 100'
INTO l_sql
FROM dba_tab_columns
where table_Name = 'DBA_OBJECTS'
group by owner, table_Name;
EXECUTE IMMEDIATE l_sql BULK COLLECT INTO l_array;
FOR i in l_array.first .. l_array.last LOOP
dbms_output.put_line(l_array(i));
END LOOP;
END;
This is how your code should look:
SELECT F1 || ', ' || F2 || ', ' || ... || ', ' || FN
FROM TABLE
NO LOOPS
Here is how you can generate code that does not use loops.
Note, if you want you can take out the where statement and generate the code for the whole database.
Test with just one table first.
SELECT 'SELECT '|| LISTAGG(COLUMN_NAME, ' || '', '' || ') || ' FROM '||TABLE_NAME as sql_stm
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME='tablename'
GROUP BY TABLE_NAME;