How to make column name dynamic with spool on ORACLE? - oracle

I want to ask, is it possible to use cursor to looping the string value? For example I have 3 title column for my '.txt' report :
COLUMN "DATE" format a15
COLUMN "SUBJECT" format a8
COLUMN "CLASS" format a10
and the result is like:
DATE SUBJECT CLASS
---------------------- ------------------ -----------------
08-Apr-2016 Science 10
08-Apr-2016 Social 11
Now, the column name is still generic or hardcode. Then, I want to return the string value to replace the "DATE", "SUBJECT" and "CLASS" to be dynamic. So just follow to the data that loaded to database.
For example :
I have table that is filled up with these data:
TITLE_COLUMN1 TITLE_COLUMN2 TITLE_COLUMN3
DATE SUBJECT CLASS
I want to select the value from TITLE_COLUMN1, TITLE_COLUMN2, TITLE_COLUMN3 to be on my column name. So what is the better way? Using
Cursor
or using
Variable
?
Thanks for the advise and help.

If you are using SQLPlus and you are speaking about substitution variables, you can make this:
column title_column1 new_value vc1
column title_column2 new_value vc2
column title_column3 new_value vc3
select title_column1,title_column2,title_column3 from test_columns;
select &vc1,&vc2,&vc3 from test_data;

Related

remove repeating data from Oracle SQL*Plus query

I am currently building a database system using oracle 10g. I have developed a query that shows an instance of an event, the customer who requested the event and the staff assigned to the event. My query returns all the correct results but I wanted to know if there is a way to delete the repeating data. For each staff member assigned the result returns the event and customer details. I have attached a picture. Is there a way to return the customer and event details only once in their columns and the corresponding records of staff assigned in that columns?
This my code
COLUMN E_ID FORMAT A7
COLUMN E_NAME FORMAT A20
COLUMN E_STIME FORMAT A30
COLUMN E_FTIME FORMAT A30
COLUMN E_COST FORMAT 9999999.99
COLUMN ET_ET_ID FORMAT A5
COLUMN V_V_ID FORMAT A5
COLUMN C_C_ID FORMAT A5
COLUMN C_FNAME FORMAT A10
COLUMN C_LNAME FORMAT A10
COLUMN S_S_ID FORMAT A5
COLUMN S_FNAME FORMAT A10
COLUMN S_LNAME FORMAT A10
COLUMN S_TASK FORMAT A20
COLUMN S_CNUM FORMAT 9999999
COLUMN ST_DESC FORMAT A20
SELECT E_ID, E_NAME, EVENT.C_C_ID ,C_FNAME, C_LNAME, E_STIME, E_FTIME, E_COST, EVENT.ET_ET_ID, EVENT.V_V_ID, EVENT_STAFF.S_S_ID, S_FNAME, S_LNAME, S_TASK, S_CNUM, STAFFTYPE.ST_DESC
FROM CUSTOMER, EVENT, EVENT_STAFF, STAFF, STAFFTYPE
WHERE EVENT.E_ID = 'E000004'
AND EVENT.C_C_ID = CUSTOMER.C_ID
AND EVENT.E_ID = EVENT_STAFF.E_E_ID
AND EVENT_STAFF.S_S_ID = STAFF.S_ID
AND STAFF.ST_ST_ID = STAFFTYPE.ST_ID;
The results in SQL plus is as shown
That's what the BREAK ON directive in SQL*Plus is for. Add to your COLUMN formatting directives:
BREAK ON E_ID ON E_NAME ...
listing all columns where you want to omit duplicates. Don't forget to use ORDER BY to ensure that records for each event and customer return in the right sequence.

Replace data of one column with substring of another column in sql loader

I am loading data from a csv file into a table using sqlldr. There is one column which is not present in every row of the csv file. The data needed to populate this column is present in one of the other columns of the row. I need to split (split(.) )that column's data and populate into that column.
Like:-
column1:- abc.xyz.n
So the unknown column(column2) should be
column2:- xyz
Also, there is another column which is present in the row but it's not what I want to input into the table. It is also needed to be populated from column1. But there are around 50 if-else cases in that. Is decode preferable to do this?
column1:- abc.xyz.n
Then,
column2:- hi if(column1 has 'abc')
if(column1 has 'abd' then 'hello')
like this there are around 50 if-else cases.
Thanks for help.
For the first part of your question, define the column1 data in the control file as BOUNDFILLER with a name that does not match a table column name which tells sqlldr to remember it but don't use it. If you need to load it into a column, use the column name plus the remembered name. For column2, use the remembered BOUNDFILLER name in an expression where it returns the part you need (in this case the 2nd field, allowing for NULLs):
x boundfiller,
column1 EXPRESSION ":x",
column2 EXPRESSION "REGEXP_SUBSTR(:x, '(.*?)(\\.|$)', 1, 2, NULL, 1)"
Note the double backslash is needed else it gets removed as it gets passed to the regex engine from sqlldr and the regex pattern is altered incorrectly. A quirk I guess.
Anyway after this column1 ends up with "abc.xyz.n" and column2 gets "xyz".
For the second part of your question, you could use an expression as already shown but call a custom function you create where you pass the extracted value and it would return the searched value from a lookup table. You certainly don't want to hardcode your 50 lookup values. You could do the same thing basically in a table level trigger too. Note I show a select statement for an example only but this should be encapsulated in a function for reusability and maintainability:
Just to show you can do it:
col2 EXPRESSION "(select 'hello' from dual where REGEXP_SUBSTR(:x, '(.*?)(\\.|$)', 1, 2, NULL, 1) = 'xyz')"
The right way:
col2 EXPRESSION "(myschema.mylookupfunc(REGEXP_SUBSTR(:x, '(.*?)(\\.|$)', 1, 2, NULL, 1)))"
mylookupfunc returns the result of looking up 'xyz' in the lookup table, i.e. 'hello' as per your example.

Cannot update a row with a bind variable in UPDATE statement

I am using Oracle SQL Developer 4.0.0.13.
Query :
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = :abc;
Field Definition : emp_device char(20 byte)
Value is : 99998000000008880999 (This value is present in the table)
When I run the above query in SQL developer it asks me to give the value for the bind variable, which I paste in the text box and it returns 0 rows updated.
But when I remove the bind variable in the update query and specify the actual value, it updates the column value. Below is the query.
Query:
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = 99998000000008880999 ;
---(works)
Also, when I add some trailing spaces in the bind variable text box and trim the emp_device column, it updates the column. Below is the query.
Query :
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = trim(:abc);
-- (works --- :abc value is '99998000000008880999 ')
I do not know what is wrong with it. Can someone please take a look and suggest a solution.
You are using CHAR type for your emp_device datatype. Note that CHAR type always blank pads the resulting string out to a fixed width.read this.
You should use VARCHAR2 as datatype if you are expecting a string or just NUMBER as your example consists purely of numeric values.
in dialog box enter your parameter as '99998000000008880999' use apostrophe chars.

convert oracle table column name to MM/DD/YYYY

I would like convert the column name to date.
for example the column name is today, i want to convert it dynamically to today's date like MM/DD/YYYY .
as of now the column name is "Today" i want it to be current date
You can't configure a column to change its name automagically. To reflect the current day or whatever else.
But, you can change the column name by using an alias when doing a query. In order to make the things the more transparent as possible, you might want to create a view. Here is an example:
-- Some table with a column named "TODAY"
CREATE TABLE T AS (SELECT LEVEL today FROM DUAL CONNECT BY LEVEL < 5);
-- Use PL/SQL to create a view on the given table
-- with a dynamic column name
DECLARE
today varchar(10) := TO_CHAR(SYSDATE,'DD/MM/YYYY');
query varchar(200) := 'CREATE OR REPLACE VIEW V'
|| ' AS SELECT today "' || today || '"'
|| ' FROM T';
BEGIN
execute immediate query;
END;
Then, to query the "table" with the right column name, you will simply need to query V instead of T:
SELECT * FROM V;
12/12/2014
1
2
3
4
If you recreate your view daily, say by calling the above PL/SQL code from a job, you will see each day a view with the current date as the column name. But, as the underlying table is left unchanged, you will still be able to query it using the canonical name today. Which is important for example if you need to perform join on that table.
That being said, I'm not sure I will push toward such a solution. Use at your own risks!
If you want the column name heading to appear as something different than what the column name is defined in the table, you simply use the as "DisplayColumnName" clause for that column:
select user_name, today as "12/12/2014" from some_table;
But you would need to programatically generate the SQL statement for that to work. What coding environment you are using would dictate how to dynamically create a select statement.

Column name is masked in oracle indexes

I have a table in oracle db which has a unique index composed of two columns (id and valid_from). The column valid_from is of type timestamps with time zone.
When I query the SYS.USER_IND_COLUMNS to see which columns my table is using as unique index, I can not see the name of the valid_from column but instead I see smth like SYS_NC00027$.
Is there any possibility that I can display the name valid_from rather than SYS_NC00027$. ?
Apparently Oracle creates a function based index for timestamp with time zone columns.
The definition of them can be found in the view ALL_IND_EXPRESSIONS
Something like this should get you started:
select ic.index_name,
ic.column_name,
ie.column_expression
from all_ind_columns ic
left join all_ind_expressions ie
on ie.index_owner = ic.index_owner
and ie.index_name = ic.index_name
and ie.column_position = ic.column_position
where ic.table_name = 'FOO';
Unfortunately column_expression is a (deprecated) LONG column and cannot easily be used in a coalesce() or nvl() function.
Use the below to verify the col info.
select column_name,virtual_column,hidden_column,data_default from user_tab_cols where table_name='EMP';

Resources