Why do I get SP2-0253 - oracle

I am getting in my test. But I think linesize is already large enough. I know increase linesize will solve the issue. Please let me know why I am getting SP2-0253 here.
SQL> COLUMN sal HEADING 'Salary' FORMAT $99,999.99
SQL> set lines 10
SQL> show user
USER is "SCOTT"
SQL> desc sal from emp
Usage: DESCRIBE [schema.]object[#db_link]
SQL> select sal from emp where rownum = 1;
SP2-0253: data item 1 ("SAL") will not fit on line
SQL> set lines 20
SQL> /
Salary
-----------
$800.00
SQL>

1) show linesize to get the current linesize. My guess is "80".
2) set linesize 32767
3) Run your SQL command. Check the actual line size.

SP2-0253: data item 1 ("SAL") will not fit on line
The reason is simple. You want the output format as:
FORMAT $99,999.99
Which needs a linesize of 11 to be displayed with proper position and alignment in SQL*Plus output.
Let's see:
SQL> set linesize 11
SQL> select sal from emp where rownum = 1;
Salary
-----------
$800.00
The simplest way to see how many lines it takes in the output is to check the LENGTH of the underline:
SQL> select length('-----------') length from dual;
LENGTH
----------
11
SQL>
So, it answers the question "why the output of 11 lines can't fit in 10 lines".
Update The actual reason for the behaviour is that the column name is formatted as new column name and there is no correct alias provided in the select list.
COLUMN commands only apply to the column names in the SELECT list when matched exactly. If they differ, then you must use the exact alias in the column list in the select statement.
Solution Add same alias name as the column name provided int he format.
SQL> COLUMN sal HEADING 'Salary' FORMAT $99,999.99
SQL> set lines 10
SQL> show user
USER is "SCOTT"
SQL> select sal from emp where rownum = 1;
SP2-0253: data item 1 ("SAL") will not fit on line
SQL> select sal Salary from emp where rownum = 1;
SALARY
----------
800
SQL>
Alternatively,
SQL> set linesize 10
SQL> select sal Salary from emp where rownum = 1;
SALARY
----------
800
SQL> select sal as "Salary" from emp where rownum = 1;
Salary
----------
800
SQL> select sal from emp where rownum = 1;
SP2-0253: data item 1 ("SAL") will not fit on line
SQL> set linesize 11
SQL> select sal from emp where rownum = 1;
Salary
-----------
$800.00
SQL>

problem is not in format but in trailing sign for negative numbers. There is no number format to avoid this. Use to_char for select your data in required format in conjunction with substr to trim result to 10 characters

Related

SQL*Plus ignores colsep option

So we are trying to dump the content of our oracle database to a .CSV file but when executing the following command
set colsep ',' echo off newpage 0 space 0 pagesize 0 linesize 3000 feed off head off trimspool on
spool C:\Users\whocares\Desktop\test.CSV
select ID, LOCATION_ID from club;
spool off
the output looks as follows:
...
17499 902
17500 902
17501 902
17502 902
17503 902
17504 902
17505 902
17506 902
17507 902
17508 902
17509 902
...
and sqlplus seems to completely ignore the set colsep ',' option.
To get a valid csv output we need to have the output look like this:
...
17499,902
17500,902
17501,902
17502,902
17503,902
17504,902
17505,902
17506,902
17507,902
17508,902
17509,902
...
So how do you properly use the set colsep option?
We don't have much experience with sqlplus and for some reason other stackoverflow solutions didn't seem to work for us.
SET COLSEP replaces SET SPACE, and that's so since Oracle 9.2 (see Obsolete SQL*Plus Commands).
If you use them both, there's no separator:
SQL> set colsep ','
SQL> select * from dept where rownum = 1;
DEPTNO,DNAME ,LOC
----------,--------------------,--------------------
10,ACCOUNTING ,NEW YORK
SQL> set space 0
SQL> select * from dept where rownum = 1;
DEPTNODNAME LOC
--------------------------------------------------
10ACCOUNTING NEW YORK
SQL> set space 1
SQL> select * from dept where rownum = 1;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
SQL>
So - remove SET SPACE.
Another option is to concatenate columns. Yes, that's a tedious job but it works, e.g.
SQL> select deptno ||','|| dname ||','|| loc from dept;
DEPTNO||','||DNAME||','||LOC
---------------------------------------------------------------
10,ACCOUNTING,NEW YORK
20,RESEARCH,DALLAS
30,SALES,CHICAGO
40,OPERATIONS,BOSTON
SQL>
If there are many tables involved, you could write a query which will write a query for you:
SQL> select 'select ' || listagg(column_name, '||'',''||') within group (order by column_id) ||
2 ' from ' || table_name result
3 from user_tab_columns
4 where table_name = 'DEPT'
5 group by table_name;
RESULT
--------------------------------------------------------------------------------
select DEPTNO||','||DNAME||','||LOC from DEPT
SQL>
Now just copy/paste the result and run it.

Mutating table error while executing row level after update trigger

I have a use case where I need to place a trigger on a table(TABLE1) whenever its column COL1 is set to 1. When this trigger executes, it should update a column of another table(TABLE2). This column gets it value from a complex query which takes input from TABLE1. Here is my trigger code:(Compiled Successfully)
CREATE OR REPLACE TRIGGER MY_TRIGGER
AFTER UPDATE ON TABLE1
FOR EACH ROW
WHEN (NEW.COL1='1')
DECLARE
Var1 Number;
Var2 Number;
BEGIN
SELECT COL3,COL2 INTO Var1,Var2 FROM TABLE1;
UPDATE TABLE2 T2
SET T2.COL1 = (Complex query joining multiple tables which takes Var1 as input and gives one column value as output- This value has to be set to T2.COL1)
WHERE T2.COL2 = Var2;
END;
In my application, TABLE1.COL1 keeps changing at run time due to different activities and I have to capture it and update my TABLE2.COL1. In this trigger there is no update being performed on TABLE1 on which trigger is defined. Still I am getting below mutating error whenever an update happens on TABLE1 at runtime. Also when my trigger is enabled the application level activities are also not letting the TABLE1 to update and giving this error.
Please help me to resolve this issue.
Getting SQL Error: ORA-04091: table DBUSERNAME.TABLE1 is mutating, trigger/function may not see it
ORA-04088: error during execution of trigger 'DBUSERNAME.MY_TRIGGER'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it
Don't select columns from the table you're modifying, it is mutating (as you already know). Use :new!
Here's an example based on Scott's EMP table.
This is a table I'll use as a target of UPDATE statement in the trigger:
SQL> create table test as select empno, sal from emp;
Table created.
Trigger: note lines #6 and #7:
SQL> create or replace trigger my_trigger
2 after update on emp
3 for each row
4 begin
5 update test t2 set
6 t2.sal = :new.sal
7 where t2.empno = :new.empno;
8 end;
9 /
Trigger created.
Testing:
SQL> select empno, sal from emp where ename = 'KING';
EMPNO SAL
---------- ----------
7839 5000
SQL> update emp set sal = 5001 where ename = 'KING';
1 row updated.
SQL> select * from test where empno = 7839;
EMPNO SAL
---------- ----------
7839 5001
SQL>

CLEAR COLUMNS Definition

I'am confused on this function clear columns. Some one can explain to me this one.
I'am using this in my script.
clear columns
COLUMN temp_in_statement new_value str_in_statement
SELECT DISTINCT
LISTAGG('''' || MONTHCOVERED || ''' AS ' || to_char(MONTHCOVERED,'MONDDYYYY'),',')
WITHIN GROUP (ORDER BY MONTHCOVERED) AS temp_in_statement
FROM (SELECT DISTINCT trunc(MONTHCOVERED) as MONTHCOVERED FROM bbsm_aaa where trunc(MONTHCOVERED) between '01-AUG-19' and '31-OCT-19');
Is there specific column/s that are cleared on this? Or all columns that I assigned was also deleted?
HELP is there for a reason :)
SQL> help clear
CLEAR
-----
Resets or erases the current value or setting for the specified option.
CL[EAR] option ...
where option represents one of the following clauses:
BRE[AKS]
BUFF[ER]
COL[UMNS]
COMP[UTES]
SCR[EEN]
SQL
TIMI[NG]
SQL>
This isn't related to columns' contents, but the way they are formatted in SQL*Plus. Have a look at this example:
First, set some columns' settings using the col command:
SQL> col empno format 9999
SQL> col ename format a5
SQL> col sal format 999g990d00
SQL>
SQL> select empno, ename, sal from emp where rownum < 4;
EMPNO ENAME SAL
----- ----- -----------
7369 SMITH 920,00
7499 ALLEN 1.600,00
7521 WARD 1.250,00
Now, clear those settings and see the difference:
SQL> clear col
columns cleared
SQL> select empno, ename, sal from emp where rownum < 4;
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 920
7499 ALLEN 1600
7521 WARD 1250
SQL>
As you can see, values in those columns weren't affected - only the way they are displayed.

Print a rollback query of a update query using a query

I need to print the rollback query of a update query.
My original query is
UPDATE EMPLOYEE SET NAME = 'SAMAN' WHERE ID=4;
The corresponding update for above query is
UPDATE EMPLOYEE SET NAME=(SELECT NAME FROM EMPLOYEE WHERE ID=4);
I need to print a query to rollback if above original query went wrong. I need it to print it via using a query also.
I'm using oracle 11g database.
You can do it by running a select query like below,
SELECT 'UPDATE EMPLOYEE SET NAME = '''||name||''' WHERE id = '||id||';' FROM employee;
and of course, run the select query before your update query.
As far as I understood the question, it is some kind of a log table you're looking for. I have no idea what you mean by "printing the rollback query"; never heard of anything like that.
So, let me demonstrate what I have on my mind. Review it, apply if it makes sense in your case. The code is commented, I hope you'll understand it
Prepare the scene:
SQL> -- Log table
SQL> create table emp_log
2 (id number constraint pk_el primary key,
3 empno number constraint fk_el_emp references emp (empno) not null,
4 datum date not null,
5 ename varchar2(20)
6 );
Table created.
SQL> -- A sequence which will be used to populate the ID column in the EMP_LOG table
SQL> create sequence seqa;
Sequence created.
SQL> -- Trigger; if new ENAME is different from the last one, log the change (i.e.
SQL> -- store the old ENAME)
SQL> create or replace trigger trg_bu_emp
2 before update on emp
3 for each row
4 begin
5 if :new.ename <> :old.ename then
6 insert into emp_log (id, empno, datum, ename)
7 values (seqa.nextval, :new.empno, sysdate, :old.ename);
8 end if;
9 end;
10 /
Trigger created.
OK, let's see how it works:
SQL> -- Some employees in department 10
SQL> select empno, ename from emp where deptno = 10;
EMPNO ENAME
---------- ----------
7782 CLARK
7839 KING
7934 MILLER
SQL> -- Update KING's name to a better one (just kidding)
SQL> update emp set ename = 'LITTLEFOOT' where empno = 7839;
1 row updated.
SQL> -- What's in the log?
SQL> select * From emp_log order by id desc;
ID EMPNO DATUM ENAME
---------- ---------- ------------------- --------------------
5 7839 30.03.2018 20:22:15 KING
SQL> -- I don't like the new name after all; return the previous one
SQL> update emp e set
2 e.ename = (select l.ename from emp_log l
3 where l.empno = e.empno
4 and l.id = (select max(l1.id) from emp_log l1
5 where l1.empno = l.empno
6 )
7 )
8 where e.empno = 7839;
1 row updated.
SQL> -- What we've done?
SQL> select empno, ename from emp where deptno = 10;
EMPNO ENAME
---------- ----------
7782 CLARK
7839 KING
7934 MILLER
SQL> -- What's in the log now?
SQL> select * From emp_log order by id desc;
ID EMPNO DATUM ENAME
---------- ---------- ------------------- --------------------
6 7839 30.03.2018 20:22:33 LITTLEFOOT
5 7839 30.03.2018 20:22:15 KING
SQL>

PL/SQL_procedure to raise emp salary has errors

The question is to write a block of codes that for those employees with a salary less than 1100, raise those people's salary by 50.
My code is as below but has error:
ERROR at line 2: Encountered the symbol "RAISE_SALARY" when expecting one of the following: := . ( # % ; immediate The symbol "; was inserted before "RAISE_SALARY" to continue.
CREATE OR REPLACE procedure raise_salary
AS
CURSOR c1 IS
select ename, sal from emp
where sal <1100
order by sal ASC;
BEGIN
FOR emp_rec IN c1
LOOP
UPDATE emp
SET sal = sal + 50;
END LOOP;
END;
/
begin
execute raise_salary;
end;
/
Search a little further, I think you'll find that the procedure didn't update the salary by 150, but actually updated by 50 the number of times equal to the number of rows returned in the cursor. In this case 3 rows (so 3 * 50 = 150) for anyone you validate. Further, it updated all salaries not only the ones in the cursor.
The update statement does not contain a WHERE clause, thus every row in the table is updated.
Further a simple update statement will accomplish what you need:
Update emp
set sal = sal + 50
where sal < 1100;
Get into the habit of thinking in terms of sets instead individual rows.

Resources