Generate range of strings - sql

Hi, everyone.
I need you help with this problem.
I need to create a bunch of serial numbers in one of my tables and for that I want to use stored procedure. So I want to pass FirstSN and LastSN as parameters to the SP and it inserts N records into my table. A serial number consists of prefix and an incremental part.
For example, I send SN0001 as FirstSN and SN0100 as LastSN and it should insert the following:
SN0001
SN0002
SN0003
...
SN0099
SN0100
How can I do that without using loops?
P.s. I am using oracle 11.2.0

select 'SN' || lpad(lvl, length('100')+1, '0') from (select level lvl from dual connect by level <= 100);

Related

combination of functions are not working properly

When i try to fetch the results using below function I'm getting only first string available under SH_CHGDESC which is FRTRV-1
string available for the SH_CHGDESC are: FRTRV-11;SFARV-13;SCRRV-12
want to fetch all available strings
If InStr ({pipe.SH_CHGDESC}, "1;") >0
then mid({pipe.SH_CHGDESC},1,InStr ({pipe.SH_CHGDESC}, "1;")-1)
Please suggest.
I think you're just trying to split a delimited string into multiple values; with your string in a CTE:
with pipe (SH_CHGDESC) as (
select 'FRTRV-11;SFARV-13;SCRRV-12' from dual
)
select regexp_substr(sh_chgdesc, '(.*?)(;|$)', 1, level, null, 1)
from pipe
connect by level < regexp_count(sh_chgdesc, '(.*?)(;|$)');
REGEXP_SUBSTR(SH_CHGDESC,'
--------------------------
FRTRV-11
SFARV-13
SCRRV-12
If you are getting the string from the table and working with multiple rows at once then it's a bit more complicated, but can be handled if there is a primary/unique key on the pipe table.

Using a temporary variable once in Oracle SQL Developer

I have a requirement for a query. It needs to select every number from a list that IS NOT present in a column. Currently, I have this working fine. This query returns every number between 1833 and 2000 that is not present in the ATTR table.
SELECT LEVEL + 1833
FROM DUAL
CONNECT BY LEVEL <= (2000 - 1833)
MINUS
SELECT ID_TX
FROM ATTR
WHERE ID_TX BETWEEN 1834 AND 2000;
What I want to do is make this as user-friendly as possible. To do that, I can enter two variables, a STARTING_ID and LIST_LENGTH. Now my query looks like this.
SELECT LEVEL + &STARTING_ID
FROM DUAL
CONNECT BY LEVEL <= &LIST_LENGTH
MINUS
SELECT ID_TX
FROM ATTR
WHERE ID_TX BETWEEN &STARTING_ID AND &STARTING_ID + &LIST_LENGTH;
At first, I was using &&, but then I could only use this query once. UNDEFINE couldn't be placed in the code block, and wasn't cleaning my variables anyway. Now my issue is that it considers each & variable to be different, so it's making the user enter 5 variables instead of 2.
How do I make it where I'm still using temporary variables (with or without the popup to enter the variable), but the person running the query only has to enter two values 1833 and 67?
A bit of a fudge but if you want the prompt for substitution variables then you can use bind variables but just populate them using substitution variables like this:
(Run it as a script using F5 and not as a statement using Ctrl+Enter)
VARIABLE list_length NUMBER;
VARIABLE start_value NUMBER;
BEGIN
:list_length := &ll;
:start_value := &sv;
END;
/
SELECT LEVEL + :start_value
FROM DUAL
CONNECT BY LEVEL <= :list_length
MINUS
SELECT ID_TX
FROM ATTR
WHERE ID_TX BETWEEN :start_value + 1 AND :start_value + :list_length;
Otherwise, just use bind variables (i.e. the query at the bottom of the script).
How about using : as prompt ?
SELECT LEVEL + :STARTING_ID
FROM DUAL
CONNECT BY LEVEL <= :LIST_LENGTH
MINUS
SELECT ID_TX
FROM ATTR
WHERE ID_TX BETWEEN :STARTING_ID AND :STARTING_ID + :LIST_LENGTH;
This employs the concept of bind variables. Thus, user could enter the necessary values and proceed.
Try to use '&&' instead of one '&'.
If a single ampersand prefix is used with an undefined variable, the value you enter at the prompt is not stored.So once the alue is substituted,variable is discarded and remains undefined. If the variable is referenced twice, even in the same statement, then you are prompted twice.
If you use '&&', the value is stored and hence you will be prompted only one.

How to read and modify the data in oracle database (instead of using Replace function)

I have just started to learn and work with Oracle SQL a few months ago, and I have a question that I could not find similar problems on Stack Overflow.
In SQL Oracle,
I am trying to find a way that I can read the data from a column and modify (add/subtract) the data. What I have got so far is using replace like here, but I do not want to use multiple replace function to make it work. I am not sure whether you guys understand my question, so I have listed what I have so far below, and I used multiple replace function.
COMMOD_CODE (Given) | MODEL(Desired_result)
|
X2-10GB-LR | X2-10GB-LR (same)
15454-OSC-CSM | 15454-OSC
15454-PP64LC | 15454-PP_64-LC
CAT3550 | WS-C3550-48-SMI
CAT3560G-48 | WS-C3560G-48PS-S
CAT3550 | WS-C3550-48-SMI
DWDM-GBIC-30 | DWDM-GBIC-30.33
Select
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(commod.COMMODITY_CODE,
'15454-OSC-CSM', '15454-OSC'),
'15454-PP64LC','15454-PP_64-LC'),
'CAT3550','WS-C3550-48-SMI'),
'CAT3560G-48','WS-C3560G-48PS-S'),
'CAT3550','WS-C3550-48-SMI'),
'DWDM-GBIC-30','DWDM-GBIC-30.33')
MODEL,
NVL(commod.COMMODITY_CODE, ' ') as COMMOD_CODE
FROM tablename.table commod
I got the the answer. However, I think I used a lot of ** REPLACE ** to get it right. So, my question is if there is any easier way to do that instead of using replace multiple times, and make your script look awful.
Is someone able to please give me some guidance?
Thanks in advance,
Use DECODE or CASE for this, I think. Or, better yet, maybe a mapping table.
You can use the DECODE function in this case:
with
test_data as (
select '15454-OSC-CSM' as COMMODITY_CODE from dual
union all select '15454-PP64LC' from dual
union all select 'CAT3550' from dual
union all select 'CAT3560G-48' from dual
union all select 'CAT3550' from dual
union all select 'DWDM-GBIC-30' from dual
)
select
decode(COMMODITY_CODE,
'15454-OSC-CSM', '15454-OSC',
'15454-PP64LC', '15454-PP_64-LC',
'CAT3550', 'WS-C3550-48-SMI',
'CAT3560G-48', 'WS-C3560G-48PS-S',
'CAT3550', 'WS-C3550-48-SMI',
'DWDM-GBIC-30', 'DWDM-GBIC-30.33')
from test_Data
;
Result:
COL
------------------
15454-OSC
15454-PP_64-LC
WS-C3550-48-SMI
WS-C3560G-48PS-S
WS-C3550-48-SMI
DWDM-GBIC-30.33
What the DECODE function does: it checks its first argument - if it is equal to the second argument, then it returns the third argument, otherwise, if it is equal to the 4th argument, it returns the 5th argument, and so on.

Printing characters one by one from a string(VARCHAR2) oracle sql without using plsql and also without using dual

I am learning SQL using ORACLE 11g. How to print a string(comes from a SELECT query), character by character in ORACLE SQL, without using dual and also without using PLSQL? Here is the sample string:
'MANOJ'
and the output should be like this:
M
A
N
O
J
I tried using LEVEL,CONNECT BY but they are not working in isqlplus. Please help!
It is a simple use of SUBSTR and CONNECT BY LEVEL. Have a look at How to split string into rows.
For example,
SQL> SELECT SUBSTR('MANOJ', level, 1) str
2 FROM dual
3 CONNECT BY LEVEL <= LENGTH('MANOJ')
4 /
S
-
M
A
N
O
J
SQL>
Not sure what you mean by "not using DUAL table", but the dual table above is just used to create the sample data for demonstration. In your case, you could use the column name instead of hard-coding the value, and you could use a sub-query in place of the dual table if your value is a result of a sub-query.

ORACLE substitute variable in IN statement

I have simple query like
SELECT * FROM temp t WHERE t.id IN (:IDs)
When executed, it prompts me (Oracle SQL Developer) for entering value if IDs variable.
When I enter for example 169, everything runs smoothly, but when I try to enter multiple IDs, like 169,170,171, I get error Invalid Number even while putting it into ''.
I'm used to working with MS SQL and MySQL, so this is little confusing to me.
Anyone any suggestions.
The problem is the varying-IN list. In SQL Developer, when you are prompted to enter the value for the bind variable, you are simple passing it as 169,170,171 which it is not considering as a set of values.
What you could do is, have multiple binds -
SELECT * FROM temp t WHERE t.id IN (:ID1, :ID2)
When prompted, enter value for each bind.
UPDATE Alright, if the above solution looks ugly, then I would prefer the below solution -
WITH DATA AS
(SELECT to_number(trim(regexp_substr(:ids, '[^,]+', 1, LEVEL))) ids
FROM dual
CONNECT BY instr(:ids, ',', 1, LEVEL - 1) > 0
)
SELECT * FROM temp t WHERE it.d IN
(SELECT ids FROM data
)
/
If you put them into ", you get error. Oracle doesn't accept ". You should use just numbers without ".
i.e: (169,170,171,...)
You can define a substitution variable as an array like so:
define IDS = (169,170,171);
and then use it like so:
SELECT * FROM temp t WHERE t.id IN &IDS;