Query related issue - oracle

I am unable to upload an image, but on my query the crime id repeats as there are two evidence types, is it possible to make it so it says Crime 1....... contains ..... Physical of which there are 1 and DNA of which there are 3?
The current result is:
Crime 1 occured on 11/12/0013 and contains evidence type: Physical of
which there are 1.
Crime 1 occured on 11/12/0013 and contains evidence type: DNA of which
there are 3.
The code is as follows:
select 'Crime' || ' ' || crime.crime_id || ' ' || 'occured on' || ' ' ||
crime.crime_date|| ' ' || ' and contains evidence type:' || ' ' ||
evidence.evidence_type || ' ' || 'of which there are' || ' '||
evidence.quantity || '.' "Crime Data"
from crime, evidence
where crime.crime_id=evidence.crime_id
order by crime.crime_id;

We can use LISTAGG() to get quite close to this.
select crime_str
|| evidence.evidence_agg_str
|| '.' "Crime Data"
from ( select crime.crime_id
, 'Crime' || ' ' || crime.crime_id || ' occured on ' ||
crime.crime_date|| ' and contains evidence type: ' as crime_str
from crime ) crime,
( select distinct crime_id
, listagg (evidence_str , ',') within group (order by evidence_type)
over (partition by crime_id) evidence_agg_str
from (
select crime_id
, evidence_type
, evidence_type || ' of which there are '||
quantity as evidence_str
from evidence )
) evidence
where crime.crime_id=evidence.crime_id
order by crime.crime_id;
As you can see from the SQL Fiddle, the sentence structure is not perfect:
Crime 1 occured on 12-NOV-13 and contains evidence type: DNA of which there are 3,Physical of which there are 1.
If this really matters to you, you can use REGEXP_COUNT to identify the last comma in the evidence string and REGEXP_REPLACE to substitute and. It depends how complicated you want to get. Find out more.

Related

Getting the number of rows with same date in a procedure (PL/SQL)

I have been working this for a while now, and I am confused as to why I am getting "exact fetch returns more than requested number of rows" error. I even followed the answer for this Udemy course but that was giving the same error as well.
This is the code:
CREATE OR REPLACE PROCEDURE GET_SALE_COUNT
(
c_order_id IN NUMBER,
c_count_sales OUT NUMBER
)
AS
c_sales_date sales.sales_date%TYPE;
c_product_id sales.product_id%TYPE;
c_customer_id sales.customer_id%TYPE;
c_salesperson_id sales.salesperson_id%TYPE;
c_quantity sales.quantity%TYPE;
c_unit_price sales.unit_price%TYPE;
c_sales_amount sales.sales_amount%TYPE;
c_tax_amount sales.tax_amount%TYPE;
c_total_amount sales.total_amount%TYPE;
BEGIN
SELECT sales_date,product_id,customer_id,salesperson_id,quantity,unit_price,sales_amount,tax_amount,total_amount
INTO c_sales_date,c_product_id,c_customer_id,c_salesperson_id,c_quantity,c_unit_price,c_sales_amount,c_tax_amount,c_total_amount
FROM sales WHERE c_order_id = sales.order_id;
DBMS_OUTPUT.put_line('Sales Date: ' || c_sales_date);
DBMS_OUTPUT.put_line('Product ID: ' || c_product_id);
DBMS_OUTPUT.put_line('Customer ID: ' || c_customer_id);
DBMS_OUTPUT.put_line('Salesperson ID: ' || c_salesperson_id);
DBMS_OUTPUT.put_line('Quantity: ' || c_quantity);
DBMS_OUTPUT.put_line('Unit Price: ' || c_unit_price);
DBMS_OUTPUT.put_line('Sales Amount: ' || c_sales_amount);
DBMS_OUTPUT.put_line('Tax Amount: ' || c_tax_amount);
DBMS_OUTPUT.put_line('Total Amount: ' || c_total_amount);
SELECT COUNT(1) INTO c_count_sales FROM sales WHERE sales_date = c_sales_date;
END GET_SALE_COUNT;
DECLARE
count_sales NUMBER;
BEGIN
GET_SALE_COUNT(1267, count_sales);
DBMS_OUTPUT.put_line('Sale Count: ' || count_sales);
END
;
If your task is to count number of rows, why are you doing other unnecessary stuff? Because, it is the first select you wrote that returns more than exactly one row (and returns TOO_MANY_ROWS error). Why did that happen? Because not only one row exists for c_order_id parameter you pass. Run that statement out of the procedure and you'll see.
Therefore, as your task isn't to do what you did, skip it and use something like this:
create or replace procedure get_sale_count
(c_order_id in number,
c_count_sales out number
)
is
begin
select count(*)
into c_count_sales
from sales a
where a.sales_date in (select b.sales_date
from sales b
where b.order_id = c_order_id);
end;
/
If you do need to display various data, then do it in a loop.

Oracle ORA-00904 error: invalid identifier

I am quite new to using Oracle. I am running a procedure to update a table. The procedure basically uses a table name and a column name as a parameter.
I am getting an ORA-00904. I looked into the error messages and researched about it, and found that my column names that I am passing might not be correct (accepted values are: less than or equal to 30 characters / alphanumeric and special characters $, _, and #)
My error message is:
Error in UV_KVS_EXTRACT_VALIDATION, error: ORA-00904: "CIT_DW_ETL"."TO_NUMBER_VALIDATE": invalid identifier, sql= select distinct uv.FRM_TRACK_ID, uv.INST_NUM, uv.TPST_SRV_CONTACT_DTE uv_value, k.value kvs_value, 'KVS_EVENT_DATA' kvs_table, k.event_id kvs_id from IM_FORMS.FRM_2450_UV_mv uv join iidb_stg.fn_frm_track_mv frm on uv.FRM_TRACK_ID = frm.frm_track_id and frm.STS_CDE in ('AER','AIP','AUD','CMP','PND','QRY') join cit_udm.event e on uv.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, '$.ID1')) and uv.INST_NUM = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, '$.ID2')) join cit_udm.KVS_EVENT_DATA k on k.event_id = e.event_id where k.key = 'TPST_SRV_CONTACT_DTE'
For example, if I follow the above error message, to me it seems that column name TPST_SRV_CONTACT_DTE is incorrect. But it is alphanumeric + less than 30 characters and has _ special character. It follows the format yet it is failing.
Below is the snippet of the procedure which might be failing:
v_sql := 'select distinct uv.FRM_TRACK_ID, uv.INST_NUM, uv.' || v_uv_column || ' uv_value, '||
' k.value kvs_value, ''' || v_kvs_table || ''' kvs_table, k.' || case when v_kvs_table = 'KVS_EVENT_DATA' then 'event_id'
when v_kvs_table = 'KVS_PRODUCT_DATA' then 'product_id' end || ' kvs_id' ||
' from IM_FORMS.' || v_uv_table || '_mv uv' ||
' join iidb_stg.fn_frm_track_mv frm on uv.FRM_TRACK_ID = frm.frm_track_id and frm.STS_CDE in (''AER'',''AIP'',''AUD'',''CMP'',''PND'',''QRY'')' ||
case when v_kvs_table = 'KVS_EVENT_DATA' then
' join cit_udm.event e on uv.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, ''$.ID1'')) and uv.INST_NUM = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, ''$.ID2''))' ||
' join cit_udm.KVS_EVENT_DATA k on k.event_id = e.event_id where k.key = ''' || v_key || ''''
when v_kvs_table = 'KVS_PRODUCT_DATA' then
' join cit_udm.product p on uv.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(p.sys_source_id, ''$.ID1'')) and uv.INST_NUM = cit_dw_etl.to_number_validate(JSON_VALUE(p.sys_source_id, ''$.ID2''))' ||
' join cit_udm.KVS_PRODUCT_DATA k on k.product_id = p.product_id where k.key = ''' || v_key || ''''
else ''
end
;
This v_sql gets used downstream in the code.
I am 90% sure it is something related to the way columns are named and where it might be occurring from, but I am clueless what and how to fix it. Is it something related to changing single quotes to double quotes?
Any comments or suggestions are most welcome.
Thanks.
error: ORA-00904: "CIT_DW_ETL"."TO_NUMBER_VALIDATE"
cit_dw_etl.to_number_validate is a function call, here:
v.FRM_TRACK_ID = cit_dw_etl.to_number_validate(JSON_VALUE(e.sys_source_id, '$.ID1'))
The error indicates that Oracle can't find the function, most likely because you don't have permission to see or execute it, or because the function hasn't been created.
I guess that your problem is in this part kvs_value, 'KVS_EVENT_DATA' kvs_table,. If you remove the 'KVS_EVENT_DATA' then it will work. I do not know what you are trying to get here.

execute immediate missing right parentheses error

I have code like below in my procedure. When I call the procedure, there is missing right parentheses error. When I test it outside the procedure, with no execute immediate clause, it works fine.
Would anyone help me pls to eliminate the mistake?
EXECUTE IMMEDIATE '
INSERT INTO prehledcen
(id_obchodu
,id_obchodu_poradi
,smer
,typceny
,vzdalenost
,hodnotaceny
,kid)
SELECT a.id_obchodu
,a.id_obchodu_poradi
,smer
,''PredchoziLast''
,predchozi_last_time - datum_obchodu
,predchozi_last
,kid
FROM middle_office.f_d_obchody_zmeny_test a
INNER JOIN (SELECT id_obchodu
,id_obchodu_poradi
,MAX(dwh_insert_process) dwh_insert_process
,MIN(insert_sysdate) insert_sysdate
FROM middle_office.f_d_obchody_zmeny_test b
GROUP BY id_obchodu
,id_obchodu_poradi) b
ON b.id_obchodu = a.id_obchodu
AND b.id_obchodu_poradi = a.id_obchodu_poradi
AND a.dwh_insert_process = b.dwh_insert_process
WHERE (datum_obchodu >= ' || v_datum_od || ' OR
(datum_obchodu < ' || v_datum_od || ' AND b.insert_sysdate >= ' || v_datum_od || '))';
I assume you have bad values for v_datum_od. Try this one:
EXECUTE IMMEDIATE '
INSERT INTO prehledcen
...
WHERE (datum_obchodu >= :d1 OR (datum_obchodu < :d2 AND b.insert_sysdate >= :d3))'
USING v_datum_od, v_datum_od, v_datum_od;

All but last line in multi-line data not appearing in SQL*Plus

Having looked high and low, I must ask ... how does this output in SQL Developer:
BUBBA GUY
P.O. BOX 123
YULEE, FL 32257
become this in SQL*Plus:
YULEE, FL 32257OX 123
Query:
SELECT FIRSTNAME || ' ' || LASTNAME || CHR(13) ||
ADDRESS || CHR(13) ||
CITY || ', ' || STATE || ' ' || ZIP || CHR(13) AS " "
FROM CITIZENS;
I understand lines/columns/data can get truncated ... but I am perplexed as to how the order of the elements in the line get mangled?
Change CHR(13) to CHR(10).
CHR(13) is the carriage return character, which causes the cursor to move back to the left edge of the screen; thus, the data from the next line overwrites the preceding line. CHR(10) is the linefeed character, which should (famous last words :-) cause the cursor to move to the next line and left edge, but that's system dependent. If changing CHR(13) to CHR(10) doesn't fix it, try changing CHR(13) to CHR(10) || CHR(13).
Share and enjoy.

Regenerate all sequences in db (oracle)

Good day. I have a very specific task: regenerate all sequences in database. There is a 400+ tables in it, so I can't do it by hands.
Can somebody help me to do it?
Thanks a lot..
Please note this is highly dangerous. You may very well make mistakes. Run the select first to check what you're about to do and create a table of the select so you can re-create the synonyms manually later if you need to.
Using all_synonyms or dba_synonyms instead of user_synonyms may result in dropping system synonyms do not do this if you want your database to work afterwards
I'd also recommend testing the code on 1 test synonym you create to ensure that it does exactly what you want.
Plus I don't really see the point of doing this at all? If the synonyms are there why do you need to re-generate them? Or is this being done on another server? If so add #server_name after user_synonyms and remove the drop.
begin
for xx in ( select * from user_sequences ) loop
execute immediate 'drop sequence ' || xx.sequence_name;
execute immediate 'create sequence ' || xx.sequence_name
|| ' start with ' || xx.min_value
|| ' ends with ' || xx.max_value
|| case when xx.cycle_flag = 'N' then ' nocycle '
else ' cycle ' end
|| case when xx.cache_size = 0 then ' nocache '
else ' cache ' end || xx.cache_size
|| case when xx.order_flag = 'N' then ' noorder '
else ' order ' end
;
end loop;
end;

Resources