Use special character '%' to append the string in update statement - sql

I need to update a table where the table column is of varchar2 datatype and need to update the value of columns with '%'.
for example --
create table test (id number, name varchar2(20));
insert into test values (1, 'smith');
insert into test values (2, 'allen');
Now we need to update the values in NAME column to smith'%'
So it should also include the single quotes in the string.
I am able to update it to smith% but it should be smith'%'
update test
set name = 'smith'||'''%'''
where id = 1;
SQL Error: ORA-00911: invalid character

Your query works perfectly in SQLPlus:
SQL> update test
2 set name = 'smith'||'''%'''
3 where id = 1;
1 row updated.
SQL> select * from test;
ID NAME
---------- --------------------
1 smith'%'
2 allen
This could be another way, avoiding the need to double the quotes:
SQL> update test
2 set name = 'allen'|| q'['%']'
3 where id = 2;
1 row updated.
SQL> select * from test;
ID NAME
---------- --------------------
1 smith'%'
2 allen'%'
Or even, avoiding the ||:
SQL> update test
2 set name = concat(name, q'['%']')
3 where id = 1;
1 row updated.
SQL> select * from test;
ID NAME
---------- --------------------
1 smith'%''%'
2 allen'%'

SQL> set define off;
verify this link
how-to-enter-special-characters-like-in-oracle-database

Actually your statement should work, I just tested it in my database.
update test
set name = concat('smith', '''%''')
where id = 1;

Related

Oracle trigger multiple conditions in when clause

I'm trying to create a trigger that updates a column in a table when other columns are updated. but getting the following error while saving the trigger
ORA-25000: invalid use of bind variable in trigger WHEN clause
My trigger is as follows, I'm not sure what is wrong with the code.
CREATE OR REPLACE TRIGGER Employees_ARIU
BEFORE INSERT OR UPDATE ON Employees
FOR EACH ROW
WHEN ((nvl(:OLD.EMP_SAL,0) != nvl(:NEW.EMP_SAL,0)) OR (nvl(:OLD.SAL_LEVEL,0) != nvl(:NEW.SAL_LEVEL,0)))
BEGIN
:NEW.LAST_UPDATED = SYSDATE
END;
Although IF is an alternative to WHEN, I'd say that it is better to use WHEN clause whenever possible because it is a
SQL condition that must be satisfied for the database to fire the trigger
So, why would you even let the trigger fire and then conclude that oh, OK, I don't want to do anything, after all? Better not running it at all!
Yes, WHEN clause has its restrictions and you can't put anything you want in there, but - your case isn't one of those.
(more info in Documentation, search for "WHEN clause").
So, for a sample table
SQL> create table employees
2 (id number,
3 emp_sal number,
4 sal_level number,
5 last_updated date);
Table created.
trigger would looks like this:
SQL> create or replace trigger employees_ariu
2 before insert or update on employees
3 for each row
4 when ( nvl(old.emp_sal, 0) <> nvl(new.emp_sal, 0)
5 or nvl(old.sal_level, 0) <> nvl(new.sal_level, 0)
6 )
7 begin
8 :new.last_updated := sysdate;
9 end;
10 /
Trigger created.
Testing:
SQL> insert into employees (id, emp_sal, sal_level) values (1, 100, 1);
1 row created.
SQL> select * from employees;
ID EMP_SAL SAL_LEVEL LAST_UPDATED
---------- ---------- ---------- -------------------
1 100 1 12.06.2021 12:14:17
SQL> update employees set sal_level = 2 where id = 1;
1 row updated.
SQL> select * from employees;
ID EMP_SAL SAL_LEVEL LAST_UPDATED
---------- ---------- ---------- -------------------
1 100 2 12.06.2021 12:14:33
SQL>
I think you can try updating your WHEN condition to IF statement along with few other changes -
CREATE OR REPLACE TRIGGER Employees_ARIU
BEFORE INSERT OR UPDATE ON Employees
FOR EACH ROW
BEGIN
IF ((nvl(:OLD.EMP_SAL,0) != nvl(:NEW.EMP_SAL,0)) OR (nvl(:OLD.SAL_LEVEL,0) != nvl(:NEW.SAL_LEVEL,0))) then
:NEW.LAST_UPDATED := SYSDATE;
END IF;
END;
/
Here is the fiddle.

is this possible? adding 4 new columns: createdDate,modifiedDate,createdBy,modifiedBy?

I'm on sql developer. I have a table. I Want to add those 4 new columns which I know how to do, but I want those values to not be entered by the user when he enters a new row or edits an existing row, I want those values to be automatically filled
For example if the user enters
insert into tableName values (val1,val2,val3)
then the table will have the 7 new values in the new row:
val1,val2,val3,createdDate,modifiedDate,createdBy,modifiedBy
same when the user modifies a value in an existing row
update TAbleName set val1 = newVal where id = id1
and then the "modifiedDate" and "modifiedBy" fields in that row will be automatically modified
What database do you use?
For auto fill when you add a new row, you need to setup "default binding" aka "default field"
ALTER TABLE YourTable
ADD CONSTRAINT DF_YourTable DEFAULT GETDATE() FOR YourColumn
For update, you need to make a trigger to edit the column
How to: Create trigger for auto update modified date with SQL Server 2008
Partially, column's default value can do that (for created date and user who did that); for modifications, use a trigger.
Here's an example:
SQL> create table test (id number, name varchar2(20));
Table created.
SQL> alter table test add
2 (created_date date default sysdate,
3 created_by varchar2(30) default user,
4 modified_date date,
5 modified_by varchar2(30)
6 );
Table altered.
SQL> insert into test (id, name) values (1, 'Little');
1 row created.
SQL> select * From test;
ID NAME CREATED_DATE CREATED_BY MODIFIED_DATE MODIFIED_B
---------- -------------------- ------------------- ---------- ------------------- ----------
1 Little 13.02.2020 22:23:17 SCOTT
Updating a row a little bit later - nothing has changed (for created and modified columns):
SQL> update test set name = 'Foot' where id = 1;
1 row updated.
SQL> select * From test;
ID NAME CREATED_DATE CREATED_BY MODIFIED_DATE MODIFIED_B
---------- -------------------- ------------------- ---------- ------------------- ----------
1 Foot 13.02.2020 22:23:17 SCOTT
Let's create a trigger. It's a simple one:
SQL> create or replace trigger trg_testmod_bu
2 before update on test
3 for each row
4 begin
5 :new.modified_date := sysdate;
6 :new.modified_by := user;
7 end;
8 /
Trigger created.
SQL> update test set name = 'Bigfoot' where id = 1;
1 row updated.
SQL> select * From test;
ID NAME CREATED_DATE CREATED_BY MODIFIED_DATE MODIFIED_B
---------- -------------------- ------------------- ---------- ------------------- ----------
1 Bigfoot 13.02.2020 22:23:17 SCOTT 13.02.2020 22:26:38 SCOTT
Right; the trigger updated both modified columns.

How to pass string data type to number datatype in plsql

I have procedure like this...
declare
v_psg varchar2(10);
id_no number;
begin
select value into v_psg from settings_am where key = 'PSG';
select id into id_no from product where to_char(psg) in (v_psg);
end;`
The value returned from select value into v_psg from settings_am where key = 'PSG'; would be
'1','2','3'
when i run this procedure i am returned with ora error - ORA-01403.
please advise how i should pass the v_psg value to psg column of product table?
EDIT - Tried with test case suggested
If you got ORA-01403, you were kind of lucky. It is the NO_DATA_FOUND error, which means that one (probably the first) query didn't return anything.
Those two statements could be combined into
select id
from product
where to_char(psg) in (select value
from settings_am
where key = 'PSG'
);
Why would you select value first, and then use it in another query? Besides, it just wouldn't work. v_psg is declared as VARCHAR2 variable. The way you described it, it contains the following string: '1','2','3', as if this is what you have:
SQL> create table settings_am (key varchar2(10),
2 value varchar2(20)); --> note size here
Table created.
SQL> insert into settings_am (key, value)
2 values ('PSG', q'['1','2','3']');
1 row created.
SQL> select * From settings_am;
KEY VALUE
---------- --------------------
PSG '1','2','3'
SQL>
As you can see, I enlarged the value column size, although variable you declared says 10. Why? Because of
SQL> select length(value) from settings_am where key = 'PSG';
LENGTH(VALUE)
-------------
11
i.e. you can't put something that is long 11 into something that accepts length 10.
Or, if your data actually contains 3 rows for the PSG key, are those values already enclosed into single quotes? If so, that's strange; people usually don't do that. Anyway, suppose that you managed to get string '1,2,3' (which is what I presume you actually have) into a VARCHAR2 variable, then you have to split it into rows in order to be able to use it in the IN clause:
SQL> create table product (id number, psg varchar2(10));
Table created.
SQL> insert into product (id, psg) values (100, '1');
1 row created.
SQL> insert into product (id, psg) values (200, '2');
1 row created.
SQL>
Query is then (where lines #3 - 5 represent splitting a string into rows):
SQL> select p.id
2 from product p
3 where p.psg in (select regexp_substr('&&v_psg', '[^,]+', 1, level)
4 from dual
5 connect by level <= regexp_count('&&v_psg', ',') + 1
6 );
Enter value for v_psg: 1,2,3
ID
----------
100
200
So, wouldn't it be simpler to use
SQL> select id
2 from product
3 where to_char(psg) in (select value
4 from settings_am
5 where key = 'PSG'
6 );
ID
----------
100
200
SQL>
Note that both options also show why your query is wrong: you can't put two values (rows) into a variable declared as id_no number; as you'd get TOO_MANY_ROWS error.
Finally, what is it that you'd want to do? What problem are you trying to solve? Apparently, except for special cases (only one row for each value) your query can't work. If you could provide test case (create table & insert into sample data), as well as expected output, it would be easier to help you.

Returning the value of identity column after insertion in Oracle

How do I return the value of an identity column (id) in Oracle 12c after insertion? Seems like most of the approaches out there uses sequence to get back the id of the inserted item.
Simply use the RETURNING clause.
For example -
RETURNING identity_id INTO variable_id;
Test case -
SQL> set serveroutput on
SQL> CREATE TABLE t
2 (ID NUMBER GENERATED ALWAYS AS IDENTITY, text VARCHAR2(50)
3 );
Table created.
SQL>
SQL> DECLARE
2 var_id NUMBER;
3 BEGIN
4 INSERT INTO t
5 (text
6 ) VALUES
7 ('test'
8 ) RETURNING ID INTO var_id;
9 DBMS_OUTPUT.PUT_LINE('ID returned is = '||var_id);
10 END;
11 /
ID returned is = 1
PL/SQL procedure successfully completed.
SQL>
SQL> select * from t;
ID TEXT
---------- --------------------------------------------
1 test
SQL>

Oracle:Set default value for number column

How can we set default value for a number typed column has '00'?I tried this but it still saved it has '0',I need to do this.
//alter table table_name add column column1 default '00';
Please suggest a way for me.
You can store as number and when you retrieve do as
select column1,to_char(column2,'00') from mytable
SQL Fiddle Demo
It is not possible to store numbers like that - In a format you have described ('00'). You can store numbers as numbers (as values of numeric data type of course) and use to_char function or to_char function combined with lpad function to represent numbers in a format you like. Here is an example:
SQL> create table TB_SingleNumberColumn(
2 col number
3 )
4 /
Table created
SQL> insert into TB_SingleNumberColumn(Col) values(1);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(5);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(11);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(111);
1 row inserted
SQL> commit;
Commit complete
-- The values as they are
SQL> select * from TB_SingleNumberColumn;
COL
----------
1
5
11
111
-- Values padded with zeros.
SQL> select to_char(col, '000') res
2 from TB_SingleNumberColumn;
RES
----
001
005
011
111
SQL> select lpad(to_char(col), 3, '0')
2 from TB_SingleNumberColumn
3 ;
LPAD(TO_CHAR(COL),3,'0')
------------------------
001
005
011
111