SPOOL in Oracle - oracle

I have this table and sample data which I want to spool in a file.
I'm not sure what is the right way to do or the syntax. I tried few ways from internet but couldn't get the right answer.
CREATE TABLE RoomType
(
RoomType Varchar2(25),
RoomTypeDesc Varchar2(50)
);
INSERT INTO RoomType VALUES ('STD', 'Standard Room');
INSERT INTO RoomType VALUES ('Business', 'Business Class');

SPOOL path/file/to/save/log.log(or txt)
PROMPT ************************************
PROMPT *** CREATION OF OBJECTS ***
PROMPT ************************************
CREATE TABLE RoomType
(
RoomType Varchar2(25),
RoomTypeDesc Varchar2(50)
);
PROMPT ************************************
PROMPT *** INSERTION ***
PROMPT ************************************
INSERT INTO RoomType VALUES (STD, 'Standard Room');
INSERT INTO RoomType VALUES (Business, 'Business Class');

Save your commands in a file with your favourite editor( like vi ), in your favourite path( let's take /home/oracle/scripts ) as a .sql file :
[oracle#DoonieDB scripts]$ vi RoomTypes.sql
set term[out] off
set feed[back] off
col RoomType format a25
col RoomTypeDesc format a25
spool /home/oracle/scripts/RoomTypes.txt
select * from RoomType;
spool off;
where col setting are used to restrict the length of the columns to keep them in single line.
Connect to your related schema and call your .sql by prefixing with a # sign and get RoomTypes.txt file with formatted info :
[oracle#DoonieDB scripts]$ pwd
/home/oracle/scripts
[oracle#DoonieDB scripts]$ sqlplus hotels/myKey
...
Connected to:
Oracle Database xxx Enterprise Edition Release 1x.x.x.x.x - 64bit Production
SQL> #RoomTypes.sql
SQL> exit
Disconnected from Oracle Database xxx Enterprise Edition Release 1x.x.x.x.x - 64bit Production
[oracle#barbdb12c scripts]$ cat RoomTypes.txt
ROOMTYPE ROOMTYPEDESC
------------------------- -------------------------
STD Standard Room
Business Business Class

Related

Remove Blank Line In Between Select Queries When Spooling to CSV File 2

I have query that is executed from SQLPLUS (11.2.0.4) and output is spooled to file. I am getting output file empty lines after each line + many empty spaces after the last column in the query. I have opened the file in notepad++ and i can see tons of empty spaces appended to the last column and ended with CRLF ( windows) , the last column is varchar 4000.
I have read tons of articles related to the same in internet but none of them help me. I have tried to set trimspool ON/OFF, trimout ON/OFF (btw - both commands are skipped ), page 0, heading off, pagesize 0, page 0, space 0, newpage nono
Example of SQL :
set termout off
set pagesize 0
set termout off
set pagesize 0
set heading off
set feedback off
set newpage none
set space 0
set linesize 8000
set longchunksize 200000
/*above was tried step by step - no help*/
spool "G:/gggg/fffff.csv"
PROMT COL1|COL2|COL3
select col1||';'||col2||';'||nvl(col3,'') abc
FROM transactions;
spool off;
output (notepad++):
COL1|COL2|COL3CRLF
col1|col2|col3 CRLF
col1|col2|col3 CRLF
col1|col2|col3 CRLF
output(linux)
COL1|COL2|COL3$
col1|col2|$
COL3 $
col1|col2|$
COL3 $
col1|col2|$
COL3 $
I have to use SQLPLUS .
it is requested to have output file without double quotes and with tilda as delimiter
e.g.
aaaa~bbbb~cccc~eeeeeeeeeeeeeeeeeeeeeeeeee
dddd~rrrr~bggggggg~rrrrrrrrrrrrrrrrrrrrrrrrrr
eeee~rrrrrrr~ttttttt~yyyyyyyyyyyyyyyyyyyyyyyyyy
Columns type :
col1 integer
col2 varchar2(4000 BYTE)
col3 varchar2(4000 BYTE)
Current output looks like
COL1NAME~COL2NAME~COL3NAME
aaaa~bbbb~cccc~eeeeeeeeeeeeeeeeeeeeeeeeee
dddd~rrrr~bggggggg~rrrrrrrrrrrrrrrrrrrrrrrrrr
eeee~rrrrrrr~ttttttt~yyyyyyyyyyyyyyyyyyyyyyyyyy
I would like to remove the empty lines without any cut of the characters in lines.
I can see in notepad++ :
COL1NAME~COL2NAME~COL3NAMECRLF
aaaa~bbbb~cccc~eeeeeeeeeeeeeeeeeeeeeeeeee..................................CRLF
dddd~rrrr~bggggggg~rrrrrrrrrrrrrrrrrrrrrrrrrr..............................CRLF
eeee~rrrrrrr~ttttttt~yyyyyyyyyyyyyyyyyyyyyyyyyy............................CRLF
I can see in linux (after less) :
COL1NAME~COL2NAME~COL3NAME$
aaaa~bbbb~cccc~eeeeeeeeeeeeeeeeeeee$
eeeeee $
$
dddd~rrrr~bggggggg~rrrrrrrrrrrrrrrr$
rrrrrrrrrr $
$
eeee~rrrrrrr~ttttttt~yyyyyyyyyyyyyy$
yyyyyyyyyyyy $
$
What's your table look like? Is COL3 defined as a CHAR or VARCHAR2? If a CHAR, that explains everything.
We need to see your data and your table, to be able to help you, otherwise you're asking us to guess.
Using the HR sample schema and the locations table, notice the varchar2's.
CREATE TABLE locations (
location_id NUMBER(4, 0),
street_address VARCHAR2(40),
postal_code VARCHAR2(12),
city VARCHAR2(30)
CONSTRAINT loc_city_nn NOT NULL ENABLE,
state_province VARCHAR2(25),
country_id CHAR(2),
CONSTRAINT loc_c_id_fk FOREIGN KEY ( country_id )
REFERENCES hr.countries ( country_id )
ENABLE
);
COUNTRY_ID is CHAR(2) - so you'll always see 2 spaces for that column, even if you only inserted '1' character.
Querying the table, with sqlformat set to CSV, I get CSV back, automatically.
SQLPlus 11.2.0.4 is approx from 2008, that's quite old.
Here's what you can do with Oracle SQLcl - smaller than SQLPlus, more powerful, and more user-friendly. Also, less code to get what you want.
SQLcl: Release 21.4 Production on Wed Feb 16 08:40:23 2022
Copyright (c) 1982, 2022, Oracle. All rights reserved.
Last Successful login time: Wed Feb 16 2022 08:40:24 -05:00
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
login.sql found in the CWD. DB access is restricted for login.sql.
Adjust the SQLPATH to include the path to enable full functionality.
SQL> set pagesize 200
SQL> cd c:\users\jdsmith\desktop
SQL> spool peeps.csv
SQL> select * from locations;
"LOCATION_ID","STREET_ADDRESS","POSTAL_CODE","CITY","STATE_PROVINCE","COUNTRY_ID"
1000,"1297 Via Cola di Rie","00989","Roma","","IT"
1100,"93091 Calle della Testa","10934","Venice","","IT"
1200,"2017 Shinjuku-ku","1689","Tokyo","Tokyo Prefecture","JP"
1300,"9450 Kamiya-cho","6823","Hiroshima","","JP"
1400,"2014 Jabberwocky Rd","26192","Southlake","Texas","US"
1500,"2011 Interiors Blvd","99236","South San Francisco","California","US"
1600,"2007 Zagora St","50090","South Brunswick","New Jersey","US"
1700,"2004 Charade Rd","98199","Seattle","Washington","US"
1800,"147 Spadina Ave","M5V 2L7","Toronto","Ontario","CA"
1900,"6092 Boxwood St","YSW 9T2","Whitehorse","Yukon","CA"
2000,"40-5-12 Laogianggen","190518","Beijing","","CN"
2100,"1298 Vileparle (E)","490231","Bombay","Maharashtra","IN"
2200,"12-98 Victoria Street","2901","Sydney","New South Wales","AU"
2300,"198 Clementi North","540198","Singapore","","SG"
2400,"8204 Arthur St","","London","","UK"
2500,"Magdalen Centre, The Oxford Science Park","OX9 9ZB","Oxford","Oxford","UK"
2600,"9702 Chester Road","09629850293","Stretford","Manchester","UK"
2700,"Schwanthalerstr. 7031","80925","Munich","Bavaria","DE"
2800,"Rua Frei Caneca 1360 ","01307-002","Sao Paulo","Sao Paulo","BR"
2900,"20 Rue des Corps-Saints","1730","Geneva","Geneve","CH"
3000,"Murtenstrasse 921","3095","Bern","BE","CH"
3100,"Pieter Breughelstraat 837","3029SK","Utrecht","Utrecht","NL"
3200,"Mariano Escobedo 9991","11932","Mexico City","Distrito Federal,","MX"
23 rows selected.
SQL> spool off
SQL>
And here's what that looks like -
If you can update your question with sample DDL and data, we can give you a better answer.
Disclaimer: I'm a product manager at Oracle for our Database tools.

how to track and modify an in-flight oracle query before execution?

My Application is sending below query to Oracle.
SELECT * FROM EMPLOYEE WHERE DATE > (SYSDATE - 1) order by employee_id
I cannot change this query from the application. I am looking for a way for oracle to monitor the queries, change it to below query format and return the result.
SELECT * FROM EMPLOYEE WHERE DATE > (SYSDATE - 1) and Currently_employed = 'YES' order by employee_id
Thank You.
Subrat
If the application can connect to the database as a different user then the table owner, you could also implement a Virtual Private Database policy to modify the query in-flight. See here:
https://oracle-base.com/articles/8i/virtual-private-databases
You could also, if the application is connecting as a separate user, create a view as suggested by #ekochergin, and have a synonym "EMPLOYEE" in the application's user schema point to the view in the data owner's schema.
If the application is connecting as the data owner, your options are much more limited. Renaming the table and replacing it with a view as suggested would be the easiest option. If you've got a lot of money to invest in Oracle's Database Application Firewall appliance you could also modify the query in-flight with a security policy there.
You might needed to rename employee table to somewhat like "EMP_TABLE" and create a view named "EMPLOYEE" using
create view employee as select * from emp_table where currently_employed = 'YES';
Please test it against a test instance before implementing on live
Use the SQL Translation Framework if you only need to convert a small number of statements. If you need to modify many statements then you should look into the options described in the other answers, such as Virtual Private Database, views, or synonyms.
For this sample schema:
create table employee
(
employee_id number,
hire_date date,
currently_employed varchar2(3)
);
insert into employee values(1, sysdate, 'NO');
insert into employee values(1, sysdate, 'YES');
commit;
Create the following translator profile and then create the specific translation:
begin
dbms_sql_translator.create_profile('EMPLOYEE_TRANSLATOR_PROFILE');
dbms_sql_translator.register_sql_translation
(
profile_name => 'EMPLOYEE_TRANSLATOR_PROFILE',
sql_text => q'[SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id]',
translated_text => q'[SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) and Currently_employed = 'YES' order by employee_id]'
);
end;
/
The translation profile must be enabled in each session. Since you have no control over the application, you can create a logon profile that will automatically run the commands to enable the translation:
--Logon trigger that enables profiles.
--I'm not sure why, but you must create this trigger as SYS.
create or replace trigger sys.logon_trg
after logon on database
--Add your username here:
when (user in ('JHELLER'))
begin
execute immediate 'alter session set sql_translation_profile = jheller.employee_translator_profile';
execute immediate q'[alter session set events = '10601 trace name context forever, level 32']';
end;
/
Now, when the application runs the original query that would normally return two rows, it will run the second query that only returns one row:
SQL> SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id;
EMPLOYEE_ID HIRE_DATE CUR
----------- --------- ---
1 12-FEB-21 YES
But be careful of tiny syntax changes that will prevent the translation. For example, if SELECT is changed to select, the query will not be replaced and will return two rows again:
SQL> select * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id;
EMPLOYEE_ID HIRE_DATE CUR
----------- --------- ---
1 12-FEB-21 YES
1 12-FEB-21 NO

Cannot read external table or read using utl_file.get_line on Windows 10 with Oracle 18c

I just upgraded to Oracle 18c XE from 11g. I have an external table that worked fine on 11g, but I keep getting the following errors on 18c.
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-11604: no directory object specified for log file
The directory does exist and I have the correct grants.
SELECT *
FROM all_directories
WHERE directory_name = 'MYDIR';
OWNER DIRECTORY_NAME DIRECTORY_PATH ORIGIN_CON_ID
SYS MYDIR C:\Users\sneuf\OneDrive\PLSQL\OracleDirectory 1
I have the required privileges.
SELECT *
FROM all_tab_privs
WHERE table_name = 'MYDIR'
AND grantee = 'C##_SNEUF';
GRANTOR GRANTEE TABLE_SCHEMA TABLE_NAME PRIVILEGE GRANTABLE HIERARCHY COMMON TYPE INHERITED
SYS C##_SNEUF SYS MYDIR EXECUTE YES NO NO DIRECTORY NO
SYS C##_SNEUF SYS MYDIR READ YES NO NO DIRECTORY NO
SYS C##_SNEUF SYS MYDIR WRITE YES NO NO DIRECTORY NO
I'm pretty sure I'm missing a grant somewhere, but I can't figure out what. Can someone please help?
Here is my table:
CREATE TABLE C##_SNEUF.CHECKING_TBL_EXT2
(
DB_KEY NUMBER,
CHECK_NUM VARCHAR2(10),
TRANS_DATE TIMESTAMP (6),
DESCRIPTION VARCHAR2(100),
DEPOSIT_WITHDRAWAL VARCHAR2(1),
AMOUNT VARCHAR2(12),
MEMO VARCHAR2(200)
)
ORGANIZATION EXTERNAL
( TYPE ORACLE_LOADER
DEFAULT DIRECTORY MYDIR
ACCESS PARAMETERS
( RECORDS DELIMITED BY NEWLINE
BADFILE MYDIR: 'checking.bad'
FIELDS TERMINATED BY ","
OPTIONALLY ENCLOSED BY '"'
LDRTRIM
MISSING FIELD VALUES ARE NULL
(
DB_key CHAR,
check_num CHAR(10),
trans_date CHAR(21) DATE_FORMAT DATE MASK 'MM/DD/YYYY HH24:MI:SS',
description CHAR(100),
deposit_withdrawal CHAR(1),
amount CHAR(12),
memo CHAR(200)
)
)
LOCATION
( MYDIR: 'checking.csv'
)
)
REJECT LIMIT UNLIMITED ;
Thanks,
Steve
Logfile isn't specified, so - by default - it resides in the same directory as the data file.
However, as you write to log file, you require write privilege on the MYDIR directory. Info you posted suggests that you have only READ privilege so - grant WRITE as well.

Alter all table columns with out white space in between names

Oracle - Alter all table column names with trim of white space in between names
For suppose column names before alter :
Home number
Mobile number
Local number
After alter column names shall be :
Homenumber
Mobilenumber
Localnumber
I've tried this way: but unable to crack:
UPDATE SA_VW_PHONENUMBER TN SET TN.Column_Name = TRIM (TN.Column_Name);
Fully automatic way
Use this cursor based DDL hacking - statement concat.
BEGIN
FOR alters IN
(
SELECT
'ALTER TABLE "'||table_name||'" RENAME COLUMN "'||column_name||
'" TO "'||replace(cols.column_name,' ','')||'"' sql_stmt
FROM all_tab_cols cols
WHERE REGEXP_LIKE(column_name,'[[:space:]]')
AND owner = user --Add real schema name here
ORDER BY 1
) LOOP
DBMS_OUTPUT.PUT_LINE ( alters.sql_stmt ||';') ;
EXECUTE IMMEDIATE alters.sql_stmt;
END LOOP;
END;
/
If you want to use the safe way
As I know you cannot perform a DDL as a dynamic SQL, so you cannot pass variables to the ALTER TABLE command, but here is what you can do instead of that.
Selecting the occurences:
SELECT table_name,column_name,replace(cols.column_name,' ','') as replace_name
FROM all_tab_cols
WHERE REGEXP_LIKE(column_name,'[[:space:]]');
Use the ALTER TABLE DDL command:
alter table T_TABLE rename column "COLUMN SPACE" TO "COLUMNNOSPACE";
Try the REPLACE function
UPDATE SA_VW_PHONENUMBER TN SET TN.Column_Name = REPLACE(TN.Column_Name,' ','')

What is Oracle Date Format and How to set that?

In MySQL :
CREATE TABLE t_users (username VARCHAR(30), password VARCHAR(30), date_added(DATE))
As I know for default format date in MySQL is like this : 2013-06-24
That worked.
Now I create table in ORACLE :
CREATE TABLE T_USERS (USERNAME VARCHAR(30), PASSWORD VARCHAR(30), DATE_ADDED(DATE))
My question is :
1. What is default date format in oracle ?
2. Can I use format like MySQL date format like this : 2013-06-24 ?
Please, need your advice.
Thank you
After connecting to oracle you can alter your session:
SQL> SELECT SYSDATE FROM DUAL;
SYSDATE
---------
24-JUN-13
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';
Session altered.
SQL> SELECT SYSDATE FROM DUAL;
SYSDATE
----------
2013-06-24
You have to run it after new connection is established.
In order to display it in different way in Oracle SQL Developer:
Tools -> Preferences -> Database -> NLS -> Date Format

Resources