Executing sql file from another sql file - sql

I have a .sql file with name Alter_table.sql which have the following code.
alter table mytable add newcolumn VARCHAR2(1);
I don't want to edit this file and add a spool command. However I need to execute Alter_table.sql by writing spool in another file (execute_sql.sql) which should look like the below. I am not sure of the correct syntax. Can anyone please help here?
SET SERVEROUTPUT ON
SET DEFINE OFF
SPOOL Alter_Table_STD_SOURCE.log
EXEC username/password#database `Alter_table.sql`
SPOOL OFF;
SET DEFINE ON
SET SERVEROUTPUT OFF

(Thanks to Alex Poole) :-)
You need to connect first, then run your .sql file in the wrapper script using the '#' sign or 'START' commands:
...
-- Connect if not already connected.
CONNECT username/password#database
#Alter_table.sql
...
I'm not sure its a good idea to keep login/password in a file but you need to take security into account.

Related

How to use spool command in sql developer oracle

Dears,
I cannot use spool command. It is not working or i am not doing something right.
I am trying to save query result in txt file (tried also csv saving with select /*csv*/ * from table but it also did not work).
So what i wrote is:
set echo off
set trimspool on
spool 'C:\Users\username\Desktop\clobams\Test1.txt'
select pn, serial_number from stock ;
spool off;
And i am getting error when pressing execute statement ORA-00900:invalid SQL statement . Sql works fine - when i execute only that part,it gives me output to the screen. How should i save my output to the file?
I have already tried to remove set echo off and set trimspool on but none of these helped
this is what i have run on my sql developer:
spool C:\Users\**direcotory**\Desktop\old desktop\sql\Test1.txt;
select * from YOUR_TABLE;
spool off;
and i got output in file test1. you need to run all commands as script.

How to pass a bash variable to sqlplus and then pass that output to another variable

So what I'm trying to do is to clear the audit logs of the PDB in an Oracle database. The name of the PDB can be different each time, so I cannot use tnsnames to sqlplus directly into the PDB to do this. I'm passing commands into bash and then passing those into a SQLPLUS command. Each of these work except for one and I can't seem to figure out how to get it to work.
My code is
AUDIT="DELETE FROM SYS.AUD$ WHERE NTIMESTAMP# < sysdate-30;"
FINDPDB="select pdb_name from dba_pdbs where pdb_name != 'PDB\$SEED';"
ALTER="alter session set container=$FINDPDB;"
sqlplus -S /nolog <<EOF1
connect / as sysdba
set echo off feedback off head off pages 0
set serveroutput on
$FINDPDB
$ALTER
$AUDIT
exit;
EOF1
The error I keep getting is
alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED';
*
ERROR at line 1:
ORA-65015: missing or invalid container name
This tells me that it's not passing the output of the select statement to $FINDPDB, but rather the actual select statement itself.
Is there a way I can pass this value to the ALTER variable and have it alter the session and clear the sys.aud$ table?
The error I keep getting is
alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED';
*
ERROR at line 1:
ORA-65015: missing or invalid container name
This tells me that it's not passing the output of the select statement to $FINDPDB, but rather the actual select statement itself.
I don't see why you would expect this to pass the output of the SELECT query into $FINDPDB. You're putting together a big long string which bash passes to the standard input of sqlplus and then writes to stdout the output from sqlplus. At no point is bash picking out certain lines of the sqlplus output and putting them into shell variables.
In fact, try adding echo $ALTER to your bash script before you call sqlplus. You will quite probably find that the output is
alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED';
If so, then bash has already done the substitution you didn't want before you've even started sqlplus.
You seem to want bash and sqlplus to have some kind of back-and-forth dialog. I would give up on this approach. Instead of trying to put the PDB name into a shell variable, I would put it into a sqlplus substitution variable. I would try something like the following (not tested):
sqlplus -S /nolog <<"EOF1"
connect / as sysdba
set echo off feedback off head off pages 0
set serveroutput on
column pdb_name new_value pdb
select pdb_name from dba_pdbs where pdb_name != 'PDB\$SEED';
alter session set container = &pdb.;
delete from sys.aud$ where ntimestamp# < sysdate - 30;
exit;
EOF1
We use column pdb_name new_value pdb to set the substitution variable pdb to the next value to be selected from a column named pdb_name. We then run a select query to fetch the PDB name and hence store it in pdb. Once we've got this value in a substitution variable, we can then issue the alter session statement to change the PDB and finally the delete statement to delete data from the PDB.
I'm tempted to avoid the use of a PL/SQL block for this, as has been suggested in another answer. I would prefer that the delete statement is parsed after the PDB is changed as I would want to be sure that the data from the 'correct' PDB is being deleted. My concern with using PL/SQL for this is that the PL/SQL compiler would determine which table to delete from when the block is parsed, which would be before it runs the block, and hence before it executes the alter session statement to change the PDB. However, I don't know PDBs and CDBs in Oracle 12c well enough to say whether this is a genuine problem or unfounded nonsense.
I don't have access to a pluggable Oracle 12c database to run something like this against, so I can't tell you whether this script works. If not, hopefully it should give you an idea of where to go.
I have no Oracle instance at hand but I see two ways to do this :
Make many connections through SQL*Plus
First, to retrieve pdb_name.
Second, to set container and delete audits.
Uses a single SQL*Plus but uses two named pipes
One to send generated SQL commands
Second to read SQL*Plus output
As alternative way I should have used a "real" programming language (Ruby, Python, JavaScript) which are better dedicated to deal with data read from database.
EDIT: After some search, it mays be done in PL/SQL
DECLARE
v_pdb_name VARCHAR2(255);
BEGIN
SELECT pdb_name INTO v_pdb_name FROM dba_pdbs WHERE pdb_name != 'PDB\$SEED';
EXECUTE IMMEDIATE 'ALTER SESSION SET container='||v_pdb_name;
DELETE FROM sys.aud$ WHERE ntimestamp# < sysdate-30;
END;
/

Oracle SQL Developer - Spooling error

I am learning SQL at the moment, and am using Oracle SQL Developer.
Right now I am having an issue with the spool command.
I insert the file path and name the file but I keep getting an "unknown command" error.
spool C:\Users\user\Desktop\AAA_Task1\output.txt
set echo on
--drop table TESTTABLE;
create table TESTTABLE (TestCol int);
set echo off
spool off
I alternate between the create and drop statements for each test.
I run the and the table is created or dropped correctly, but I get a line one error "Unknown Command" and no text file is created.
I have attached a picture of a test command and the error.
If someone could point me in the right direction I would be grateful.
There is difference between run script and run statement, see here.
Use following commands and run script.
spool 'C:\Users\user\Desktop\AAA_Task1\output.txt'
set echo on
--drop table TESTTABLE;
create table TESTTABLE (TestCol int);
set echo off
spool off
Making the file path in quotes did not work for me in the Oracle database.
spool data.txt
set echo on
Query -- the query
set echo off
spool off
this will save the query and output to the data.txt file in the
"C:\Users\NELSON JOSEPH\AppData\Roaming\SQL Developer\data.txt" in this location likewise username varies for others.

set serveroutput ON permanently?

I am new in oracle and doing practice for the PL/SQL. I have one question i.e. :
how to set serveroutput ON permanently in oracle. Is their any way that we use to set it permanently ON?
If you are refering to SQL*Plus you should set this in your glogin.sql file.
You can find this file in ORACLE_HOME\sqlplus\admin.
As far as I know there is no way of setting server output ON permanently.
But if this question is connected to fact that for every new session in SQL developer, 1 needs to execute SET SERVEROUTPUT ON statement in beginning for seeing PL/SQL code result, then solution is Go to view->DBMS_Output
Then below you will see dbms output window. There is a plus(+) button there. Click and add schema on which you are working currently. Then PL/SQL script output can be seen there.

Can we delete the physical file from server when I delete the corresponding entry from database?

Can we delete the physical file from server when I delete the corresponding entry from database?
i.e., C:\Test\Test.txt -> when deleting this record from database, i need to delete the corresponding Test.txt file from mentioned location.
Is there a way, I m using SQL 2008.
Any help would be highly appreciable..
Thanks
The ways are:
use of xp_cmdshell proc (exec master..xp_cmdshell 'del C:\Test\Test.txt')
use the .NET CLR unsafe proc (need to write in any .NET language and deploy to sql server. Its a long story)
Both ways are ugly
And once again - it is the worst practice. Server should not delete user files, or any files, is they are not integral part of its database.
You could use CREATE TRIGGER FOR DELETE to create a trigger that runs when rows are deleted. The SQL statement that is run upon deletion can walk through the table deleted to get the deleted rows. For each row it can exec xp_cmdshell. xp_cmdshell is disabled by default, so you must enable it first using exec sp_configure.
I didnt tested this but i think it should work.
Try writing a stored procedure which has the filename as a parameter and delete it using the:
exec master.dbo.xp_cmdshell 'del <Filename>'
then create a trigger for after delete on the table containing the Filenames which calls the stored procedure and provides the Filename from table deleted, or maby you can run directly the command exec master.dbo.xp_cmdshell 'del ' from the trigger.
The better way would be to save the files as an Object in the Database instead of the file path, and when deleting you just delete the file Object.