sqlplus pass a string containing ' ' such as 'index1','index2','index3' - oracle

I need to pass this value to my sql file cause I am executing then a where condition with a IN.
For instance : Delete FROM table WHERE col IN ('index1','index2','index3')
I have an issue when I try to call this sql file from cmd using sqlplus command
set INDEXES = 'index1','index2','index3'
sqlplus script %INDEXES%
When I do that, only index1 is passed or there is a problem
I tried to do that
set INDEXES = "'index1','index2','index3'"
sqlplus script %~INDEXES%
but there is a problem too
Here is my sql:
Delete FROM table WHERE col IN (&1)
Do you have any idea how I can successfully pass the string I need ?
thank you

Oracle does not come with a built-in string tokenizer. So, we have to build our own. There are several different solutions on SO. Here is one I published, which will work on 10g or higher. For earlier versions try this one.

Actually, your technique is correct.
sqlplus scott/tiger #script.sql "'index1','index2','index3'"
where script.sql is:
Delete FROM table WHERE col IN (&1)
will result in &1 being replaced, verbatim, with 'index1','index2','index3', resulting in sqlplus executing:
Delete FROM table WHERE col IN ('index1','index2','index3')
The problem i see is that the delete statement doesn't end in a semi-colon and the script doesn't commit/exit (maybe those were just excluded in your post).
So it follows that, if your command-line properly interpolates environment variables, then
set INDEXES = "'index1','index2','index3'"
sqlplus scott/tiger #script.sql %~INDEXES%
results in the same command as the first in my comment.
An easy way to see what sqlplus is doing with the command-line parameters is to simply add prompt to the beginning of the delete line in your script:
prompt Delete FROM table WHERE col IN (&1)

I would look at this as a variable in list question. These can be tricky and the answer varies based on the version of Oracle you have access to
create table aaa(aaa varchar2(50));
insert into aaa values('index1');
insert into aaa values('index2');
insert into aaa values('index3');
insert into aaa values('index4');
insert into aaa values('index5');
declare
pindexes varchar2(100) ;
begin
pindexes := 'index1,index2,index3';
delete aaa where aaa in (
select substr(pindexes,
loc+1,
nvl(
lead(loc) over (order by loc) - loc-1,
length(pindexes) - loc)
)
from (
select distinct (instr(pindexes, ',', 1, level)) loc
from dual
connect by level < length(pindexes)
)
);
end ;
/
select * from aaa;
/
--drop table aaa;
this way you just pass in your string as 'index1,index2,index3'
this should work 9i+
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:210612357425

Related

How to create a procedure to remove all special characters and duplicate records

I want to create a procedure to remove all special characters from a column of my spesific table and then remove duplicate records.
I tried the following query so far to show the desired logic :
SELECT ft_nm_val,count(*)
FROM ( SELECT REGEXP_REPLACE(ft_nm_val, '[^A-Za-z0-9, ]') AS ft_nm_val
FROM fraud_token_name )
GROUP BY ft_nm_val
HAVING COUNT(*) > 1
Since you want to remove duplicate records and if there are other columns exist in the table, then concept duplicate would change row-wisely. So, I assume you have that table with only one column mentioned. Then you can create such a procedure :
SQL> create or replace procedure make_unique is
begin
--# Leave only alpha-numeric characters through applying [^ ] to [:alnum:] posix
update fraud_token_name
set ft_nm_val = regexp_replace(ft_nm_val,'[^[:alnum:]]');
--# Then delete duplicate records
delete fraud_token_name f1
where rowid <
(
select max(rowid)
from fraud_token_name f2
where f2.ft_nm_val = f1.ft_nm_val
);
commit;
end;
/
SQL> exec make_unique;
Demo

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,' ','')

How to update string value by string comparison condition PL/SQL

I want update all values in my tables, but this can kill my database
UPDATE Table_1
SET Value = 'Some string with but changed'
where value = 'Some string without changes';
Can I do this by procedures, and it guarantee that it will not perform in infinty please i need some tips?
Edit
I read about cursors, but how can i use it
Your SQL seems fine and that is the preferred solution. A cursor will normally be far, far slower.
If you cannot create an index and the update above is really that slow, try the following. Considering I don't have the rest of the table definition to work with, I assume your primary key is a single field named ID:
First, create a temporary table with only the matching records:
CREATE TEMPORARY TABLE temp as
SELECT *
FROM Table_1
WHERE value = 'Some string without changes';
Then, update using this temporary table:
UPDATE Table_1 SET
Table_1.Value = 'Some string with but changed'
WHERE EXISTS (
SELECT *
FROM Temp
WHERE Temp.ID = Table_1.ID
);
Another approach if your DB is higher than 11g R1 version. Oracle has provided a beautiful package called DBMS_PARALLEL_EXECUTE which is used for large DMLS or any process which can be split into chunks and can be parallely done.

When or Why to use a "SET DEFINE OFF" in Oracle Database

I'm watching a Script in Oracle and I see something I don't recognize
REM INSERTING into database1."Users"
SET DEFINE OFF;
Insert into database1."Users" ("id","right") values ('1','R');
I'm looking for documentation about "set define off" and it's literally writing "disable the parsing of commands to replace substitution variable with their values"
I don't really understand what they want to say.
Can anyone help me?
By default, SQL Plus treats '&' as a special character that begins a substitution string. This can cause problems when running scripts that happen to include '&' for other reasons:
SQL> insert into customers (customer_name) values ('Marks & Spencers Ltd');
Enter value for spencers:
old 1: insert into customers (customer_name) values ('Marks & Spencers Ltd')
new 1: insert into customers (customer_name) values ('Marks Ltd')
1 row created.
SQL> select customer_name from customers;
CUSTOMER_NAME
------------------------------
Marks Ltd
If you know your script includes (or may include) data containing '&' characters, and you do not want the substitution behaviour as above, then use set define off to switch off the behaviour while running the script:
SQL> set define off
SQL> insert into customers (customer_name) values ('Marks & Spencers Ltd');
1 row created.
SQL> select customer_name from customers;
CUSTOMER_NAME
------------------------------
Marks & Spencers Ltd
You might want to add set define on at the end of the script to restore the default behaviour.
Here is the example:
SQL> set define off;
SQL> select * from dual where dummy='&var';
no rows selected
SQL> set define on
SQL> /
Enter value for var: X
old 1: select * from dual where dummy='&var'
new 1: select * from dual where dummy='X'
D
-
X
With set define off, it took a row with &var value, prompted a user to enter a value for it and replaced &var with the entered value (in this case, X).

DB2 for IBM iSeries: IF EXISTS statement syntax

I am familiar with Sybase which allows queries with format: IF EXISTS () THEN ... ELSE ... END IF (or very close). This a powerful statement that allows: "if exists, then update, else insert".
I am writing queries for DB2 on IBM iSeries box. I have seen the CASE keyword, but I cannot make it work. I always receive the error: "Keyword CASE not expected."
Sample:
IF EXISTS ( SELECT * FROM MYTABLE WHERE KEY = xxx )
THEN UPDATE MYTABLE SET VALUE = zzz WHERE KEY = xxx
ELSE INSERT INTO MYTABLE (KEY, VALUE) VALUES (xxx, zzz)
END IF
Is there a way to do this against DB2 on IBM iSeries? Currently, I run two queries. First a select, then my Java code decides to update/insert. I would rather write a single query as my server is located far away (across the Pacific).
+UPDATE+
DB2 for i, as of version 7.1, now has a MERGE statement which does what you are looking for.
>>-MERGE INTO--+-table-name-+--+--------------------+----------->
'-view-name--' '-correlation-clause-'
>--USING--table-reference--ON--search-condition----------------->
.------------------------------------------------------------------------.
V |
>----WHEN--+-----+--MATCHED--+----------------+--THEN--+-update-operation-+-+----->
'-NOT-' '-AND--condition-' +-delete-operation-+
+-insert-operation-+
'-signal-statement-'
See IBM i 7.1 InfoCenter DB2 MERGE statement reference page
DB/2 on the AS/400 does not have a conditional INSERT / UPDATE statement.
You could drop the SELECT statement by executing an INSERT directly and if it fails execute the UPDATE statement. Flip the order of the statements if your data is more likely to UPDATE than INSERT.
A faster option would be to create a temporary table in QTEMP, INSERT all of the records into the temporary table and then execute a bulk UPDATE ... WHERE EXISTS and INSERT ... WHERE NOT EXISTS at the end to merge all of the records into the final table. The advantage of this method is that you can wrap all of the statements in a batch to minimize round trip communication.
You can perform control-flow logic (IF...THEN...ELSE) in an SQL stored procedure. Here's sample SQL source code:
-- Warning! Untested code ahead.
CREATE PROCEDURE libname.UPSERT_MYTABLE (
IN THEKEY DECIMAL(9,0),
IN NEWVALUE CHAR(10) )
LANGUAGE SQL
MODIFIES SQL DATA
BEGIN
DECLARE FOUND CHAR(1);
-- Set FOUND to 'Y' if the key is found, 'N' if not.
-- (Perhaps there's a more direct way to do it.)
SET FOUND = 'N';
SELECT 'Y' INTO FOUND
FROM SYSIBM.SYSDUMMY1
WHERE EXISTS
(SELECT * FROM MYTABLE WHERE KEY = THEKEY);
IF FOUND = 'Y' THEN
UPDATE MYTABLE
SET VALUE = NEWVALUE
WHERE KEY = THEKEY;
ELSE
INSERT INTO MYTABLE
(KEY, VALUE)
VALUES
(THEKEY, NEWVALUE);
END IF;
END;
Once you create the stored procedure, you call it like you would any other stored procedure on this platform:
CALL UPSERT_MYTABLE( xxx, zzz );
This slightly over complex piece of SQL procedure will solve your problem:
IBM Technote
If you want to do a mass update from another table then have a look at the MERGE statement which is an incredibly powerful statement which lets you insert, update or delete depending on the values from another table.
IBM DB2 Syntax

Resources