Cannot insert empty string in oracle table - oracle

i am trying to insert data into one of my table.
insert into t_transaction_query_log
(log_id,
posting_id,
fee_id,
fee_status,
fee_type,
pay_mode,
accounting_date,
policy_id,
money_id,
finish_time,
source_type,
fee_amount,
cr_seg,
dr_seg,
product_id' || v_insert_str_cr_seg ||
v_insert_str_dr_seg || ')
select s_transaction_query_log__lg_id.nextval,
tg.je_posting_id,
tg.fee_id,
tg.fee_status,
tg.fee_type,
60,
tg.accounting_date,
tg.policy_id,
tg.currency_id,
trunc(sysdate,
''dd''),
2,
tg.fee_amount,' ||v_str_cr_seg
|| ',' || v_str_dr_seg || ',
tg.product_id' || v_insert_str_cr_seg ||
v_insert_str_dr_seg || '
from t_ri_fee_gl tg
where tg.posted = ''Y''
i have declared v_str_cr_seg,v_str_dr_seg as empty strings i.e v_str_dr_seg varchar(50)='';
before executing this query i am able to append some values to these two strings
but in case there is no change in these strings from the declaration
i am getting the computed query as
insert into t_transaction_query_log
(log_id,
posting_id,
fee_id,
fee_status,
fee_type,
pay_mode,
accounting_date,
policy_id,
money_id,
finish_time,
source_type,
fee_amount,
cr_seg,
dr_seg,
product_id)
select s_transaction_query_log__lg_id.nextval,
tg.je_posting_id,
tg.fee_id,
tg.fee_status,
tg.fee_type,
60,
tg.accounting_date,
tg.policy_id,
tg.currency_id,
trunc(sysdate,
'dd'),
2,
tg.fee_amount, , ,
tg.product_id
from t_ri_fee_gl tg
where tg.posted = 'Y'
which in turn results in missing expression error.
i have tried using nvl function as
nvl(v_str_cr_seg, '') and `nvl(v_str_cr_seg, null)`
but still i am getting the same error
how can i insert even though v_str_cr_seg and v_str_dr_seg are unchanged
i.e empty strings ''

Ora DB:
empty string = null
enter link description here
Note:
Oracle Database currently treats a character value with a length of zero as null. However, this may not continue to be true in future releases, and Oracle recommends that you do not treat empty strings the same as nulls.

If this is an insert Statement in the middle of a PL/SQL Routine, then you would not string concatenate. It would rather look like this
tg.fee_amount, v_str_cr_seg, v_str_dr_seg
But something from your question tells me that you are composing a string that you want to execute immediate.
In this case you have to make sure you are giving quotes:
tg.fee_amount,''' ||v_str_cr_seg
|| ''',''' || v_str_dr_seg || ''',
tg.product_id''' || v_insert_str_cr_seg ||
v_insert_str_dr_seg || '''
You need to escape the single quote (') with two quotes in a row ('')
But if your strings already come with quotes around it unless null you may want to work with nvl this way
tg.fee_amount,' ||nvl(v_str_cr_seg,'''''')
|| ',' || nvl(v_str_dr_seg,'''''') || ',

Try using chr(0) instead of ''. Null character is a sign of the end of a string.

Related

In Oracle execution time for finding a data inside comma seperated column taking too long

I am trying to find out if the list of data is in comma separated column. I have a code select * from my_table where (regexp_substr ( listcolumn, '[^,]+', 1, level ) in ('a','d')) connect by level <= regexp_count(listcolumn, ',') + 1; and table with a lot data. The problem is it works for small data table but it is taking too much time to execute for a lot a table with a lot of data. I am not expert in database. so can you please help to how to resolve this problem. Thank you in advance.
Don't split the string, look for a sub-string match (with the surrounding delimiters so that you match entire terms):
SELECT *
FROM my_table
WHERE ',' || listcolumn || ',' LIKE '%,' || 'a' || ',%'
OR ',' || listcolumn || ',' LIKE '%,' || 'd' || ',%';

Can you Insert a Carriage Return within a listagg function that is also concatenating different elements?

I am currently attempting to aggregate a list of concatenated values. However, I was wondering if it was possible to use a carriage return function within the listagg so that each concatenated value would be returned onto a new line. Does anyone have any experience with this? Thank you!
Here is a portion of my code: (Please note that this is also taking place inside a view join)
(select (listagg ((z.event_name || ' - ' || z.event_date), '; ') within group
(order by z.event_name))
from
a_visit_event z
where
z.subject_no = av.subject_no
and
z.visit_date = av.visit_date) event_name,
Just add chr(13)
i.e.
listagg ((z.event_name || ' - ' || z.event_date), '; '||chr(13))

PL/SQL: Exclamation Mark in ORACLE

What are those exclamation(!) marks in the following query?
l_sql := q'!
SELECT CASE WHEN FILTER_CNT = 0 THEN NULL ELSE FILTER_LIST END AS FILTER_LIST
FROM
(
SELECT 'TABLE_NAME NOT LIKE ' || LISTAGG(''''||EXCLUSION_CRITERIA||'''', ' AND TABLE_NAME NOT LIKE ') WITHIN GROUP (ORDER BY ROWNUM) AS FILTER_LIST, COUNT(*) AS FILTER_CNT
FROM !'|| p_after_owner ||q'!.UT_TABLE_EXCLUSION
WHERE EXCLUSION_TYPE = 'P'
)
!';
The q method of quoting strings means that you don't have to escape single quotes in the string.
As per the documentation, it works like this:
q'<single character delimiter><text><single character delimiter>'
Therefore, the !s in your sample string are acting as the quote delimiter.
For example, if you want to use the string Don't worry, be happy, in the old style quoting, that would become:
'Don''t worry, be happy'
but the new quoting mechanism would be:
q'!Don't worry, be happy!'
or
q'{Don't worry, be happy}'
etc.

Condense AND clause Oracle sql

I've come across this in one of the sql scripts we have for one of our apps. I notice that it's used in various other places, but isn't it just checking for an existence of an item?
AND INSTR((SELECT (',' || REPLACE('OWN, JO', ' ', NULL) || ',') b FROM DUAL),
(',' || aao.AcctRoleCd || ',')) > 0
Where it's looking to see if 'OWN' or 'JO' is in aao.AcctRoleCd. If it is then INSTR would result in its index in the string, so it'll be greater than one. So the AND clause would be true.
Isn't this poor to check if an item exists like this? Would something more of the lines of an IN clause be better?
AND aao.AcctRoleCd IN ('OWN', 'JO');
Almost:
'OWN, JO' is a text literal.
REPLACE('OWN, JO', ' ', NULL) just strips the space from the string giving 'OWN,JO'.
',' || 'OWN,JO' || ',' just concatenates commas to the start and end of the string giving ',OWN,JO,'.
(SELECT ',OWN,JO,') b FROM DUAL) is redundant and you can just use the previous text literal.
INSTR( ',OWN,JO,', (',' || aao.AcctRoleCd || ',') ) > 0 is looking for a comma at the start and end of the substring which equals aao.AcctRoleCd so could match either 'OWN', 'JO' or 'OWN,JO'.
So you can replace it with:
AND aao.AcctRoleCd IN ( 'OWN', 'JO', 'OWN,JO' )
Now, it may be that 'OWN,JO' is not a match you are expecting (or may not even be a valid value) and you can strip it from the list but that is something you will need to determine.
You are right, but thanks for sharing that surprisingly bad code.
(SELECT (',' || REPLACE('OWN, JO', ' ', NULL) || ',') b FROM DUAL)
is a completely unnecessary scalar subquery. It could be replaced by
',' || REPLACE('OWN, JO', ' ', NULL) || ','
However, since that snippet has only literals then it could be further replaced by the result:
,OWN,JO,
and yes, it would seem that whole INSTR could be replaced by the code you suggest, unless aao.AcctRoleCd could contain 'N,J' or some such in which case the original code and your code would get different results. I seriously doubt that is a problem.
Best regards, Stew

How to use SELECT result record as DECODE parameters?

Is it possible to use SELECT result as DECODE parameters when this SELECT returns only one record with prepared string?
For example:
SELECT replace(replace(serialized_data)..)..) as result FROM table
Returns following result in ONE ROW:
0,'label0',1,'label1',2,'label2'
But when I put this to DECODE it's being interpreted as ONE PARAMETER.
Is there possiblity to convert this result "string" to "pure" sql code? ;)
Thanks for any help.
You could kind of replicate decode by use of instr and substr. An example below (which could probably be tidied up considerably but works):
select DTXT
,Nvl(
Substr(
DTXT
,Instr(DTXT, SEARCHTXT || VALMTCH)
+ Length(SEARCHTXT || VALMTCH)
, Instr(DTXT, VALSEP, Instr(DTXT, SEARCHTXT || VALMTCH))
- Instr(DTXT, SEARCHTXT || VALMTCH)
- Length(SEARCHTXT || VALMTCH))
,CASEOTHER)
as TXTMATCH
from (select '0=BLACK;1=GREEN;2=YELLOW;' as DTXT
,'1' as SEARCHTXT
,';' as VALSEP
,'=' as VALMTCH
,'OTHER' as CASEOTHER
from Dual)
You do need to have a semi-colon (VALSEP) at the end of the text though to ensure you can find the last value (though it's possible to work around that if I looked into it further).
list_agg or wm_concat depending on version of oracle.
http://docs.oracle.com/cd/E14072_01/server.112/e10592/functions087.htm
You can use dynamic SQL:
declare
DECTXT varchar2(4000);
begin
select replace(replace(serialized_data)..)..) as result into dectxt from table;
execute immediate 'select decode(col1,' || DECTXT || ') from tab1';
end;
This is just a quick example, not showing any output, etc.

Resources