This is driving me crazy. I want to do simple comparison of a column and a variable but it just doesn't work. The following line always counts all of the tuples while I only need those as conditioned by the where clause.
SELECT count(*) INTO cnt from class where class.fid = fid;
It looks sooooo simple but I've been working on this for hours. The complete sql proc is
The big confusing thing is that if I replace fid with some hard coded ID (like 105) it gives a correct answer), but when I use fid it just doesn't work any more and returns count of all classes. For some reason, always class.fid = fid. When I use >, < or <>, 0 count is returned!
create or replace PROCEDURE pro_report2
AS
CURSOR c_dept IS select deptid, dname from department;
TYPE cur_typ IS REF CURSOR;
c1 cur_typ;
query_str1 VARCHAR2(200);
fid faculty.fid%type := 102;
fname faculty.fname%type;
cnt NUMBER;
BEGIN
FOR dept_row in c_dept LOOP
DBMS_OUTPUT.PUT_LINE('Dept.Name: ' || dept_row.dname);
DBMS_OUTPUT.PUT_LINE('Faculty Name' || chr(9)|| chr(9) || '0 Class' || chr(9) || chr(9) || '1 Class' || chr(9) || chr(9) || '2 Classes' || chr(9) || '>2 Classes');
DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
--find all faculty in this department
query_str1 := 'select fid, fname from faculty where faculty.deptid = ' || to_char(dept_row.deptid);
open c1 for query_str1;
LOOP
FETCH c1 into fid, fname;
exit when c1%notfound;
DBMS_OUTPUT.PUT_LINE(fname);
SELECT count(*) INTO cnt from class where class.fid = fid;
DBMS_OUTPUT.PUT_LINE(to_char(cnt) || ' ' || to_char(fid));
END LOOP;
-- Spaces between departments
DBMS_OUTPUT.PUT_LINE(chr(10));
DBMS_OUTPUT.PUT_LINE(chr(10));
END LOOP;
END;
Thanks
I believe you need to rename or prefix your local variable fid as it unfortunately matches the column name in the table you are querying. The SQL engine is simply comparing fid = fid for each row, which will always be true (excepting nulls, but that's another story). Plus, it's harder to read your code when you have variables named the same as a column.
In PL/SQL there tends to be a convention to prefix local variables with a l_ (for local) so it's clear what the purpose is. However, any name other than a column name will suffice. Try:
l_fid faculty.fid%type := 102;
And then...
SELECT count(*) INTO cnt from class where class.fid = l_fid;
(Plus other appropriate replacements.)
Related
My SELECT count function returns the number of kids in a specific profile that has in id (secte = id_profile). When I input an invalid profile, the select statement returns an empty table insead of an error that I can solve. Any tips? (The tables are created by me);
CREATE OR REPLACE FUNCTION bursieri(sectie profile.id_profile%type)
return number IS
numar number(3) := 0;
BEGIN
select count(s.first_name) into numar
from student s, profile p,class c
where s.id_class = c.id_class and c.id_profile = p.id_profile
and p.id_profile=sectie;
return numar;
END bursieri;
/
--profilul 71
BEGIN
dbms_output.put_line('Exista ' || bursieri(9100) || ' studenti bursieri');
END;
I tried to give an invalid profile id and expected an error, but instead I got an empty table
I have a statement I'm trying to construct in Oracle 18c. The following line works fine:
Select JSON_VALUE(l_resp, '$.items[0].volumeInfo.industryIdentifiers[1].type')
into l_temp_var
from dual;
However, I have to vary the second index by a variable. The second index currently contains [1]. I tried using [i] defined as a numeric or varchar, but that doesn't work. How can I construct a Select JSON_VALUE statement so that it uses a variable?
Thanks for looking at this.
Use string concatination to build your index string. For example:
BEGIN
FOR i IN 1..10 LOOP
Select JSON_VALUE(l_resp, '$.items[0].volumeInfo.industryIdentifiers[' || i || '].type')
into l_temp_var
from dual;
-- Do something with the value in l_temp_var here
END LOOP;
END:
I couldn't make the concatenation work. I tried another approach. I had to put the "type" and "identifier" into a Json table.
--Obtain the NVP values of "industryIdentifiers" e.g. ISBN_10, ISBN_13 .
For rowz in
(select *
from json_table(l_resp, '$.items[0].volumeInfo.industryIdentifiers[*]'
columns (ii_type varchar2(512) path '$.type',
ii_identifier varchar2(512) path '$.identifier'
)
) j_ii_tab
)
Loop
/*
If rowz.ii_type = 'ISBN_10' Then
:P133_ISBN_10 := rowz.ii_identifier;
Elsif rowz.ii_type = 'ISBN_13' Then
:P133_ISBN_13 := rowz.ii_identifier;
End If ;
*/
dbms_output.put_line('ii_type: ' || rowz.ii_type);
dbms_output.put_line('ii_identifier: ' || rowz.ii_identifier);
End Loop rowz;
It might be helpful to see the Json data at: https://www.googleapis.com/books/v1/volumes?q=isbn:9781484204856
I have to recreate a stored procedure which existed in DB1, and map the existing tables to new tables in the new database DB2.
In DB1, table there was column Fullname and in the new db there are two columns firstname, lastname. I could have concat but there is a user defined function also which truncates all special characters which I have to use.
How do I use the first name and last name columns as one full name column so that it fits this case statement?
I am getting the [P Name] from another table enrolled enr which is like the master table having all the names, getting names from either tables is conditioned as shown in case statement.
I tried searching all blogs and stackexchange but cannot get the desired reply.
masterfinancer = dbo.fn_RemoveSpecialChars(iif(enr.p_name = 'XXXXXXXXX,XXXXXXX(2)', 'XXXXX XXXX XXX GROUP', mv.master_vendor_name))
Sma_finace_key = iif(enr.p_name = 'XXXXXXXXX0L(2)', 1111, mv.ven_key)
[P Name] = case
when enr.p_name = 'INACTIVE ' or enr.p_name = 'UNASSIGNED'
then [P Name]
else dbo.fn_RemoveSpecialChars(enr.p_name)
end
You'll need to use the function on each separate field and join them together. Here I removed the IIF statements (which only work in SQL 2012) and created a FullName field that assumes you want "First, Last". I added COALESCE to avoid the FullName field being NULL when either the first or last names are NULL:
SELECT
masterfinancer = dbo.fn_RemoveSpecialChars(
CASE
WHEN enr.p_name = 'XXXXXXXXX,XXXXXXX(2)'
THEN 'XXXXX XXXX XXX GROUP'
ELSE mv.master_vendor_name
END)
, Sma_finace_key =
CASE
WHEN enr.p_name = 'XXXXXXXXX0L(2)'
THEN 1111
ELSE mv.ven_key
END
, [P Name] =
CASE
WHEN enr.p_name IN('INACTIVE ', 'UNASSIGNED')
THEN [P Name]
ELSE dbo.fn_RemoveSpecialChars(enr.p_name)
END
, FullName =
COALESCE(dbo.fn_RemoveSpecialChars(enr.last_name) + ', ', '') +
COALESCE(dbo.fn_RemoveSpecialChars(enr.first_name), '')
I met a problem when calling a user-defined function in MySQL. The computation is very simple but can't grasp where it went wrong and why it went wrong. Here's the thing.
So I created this function:
DELIMITER //
CREATE FUNCTION fn_computeLoanAmortization (_empId INT, _typeId INT)
RETURNS DECIMAL(17, 2)
BEGIN
SET #loanDeduction = 0.00;
SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
INTO #totalAmount, #periodicDeduction, #totalInstallments, #deductionFlag
FROM loans_table
WHERE TypeId = _typeId AND EmpId = _empId;
IF (#deductionFlag = 1) THEN
SET #remaining = #totalAmount - #totalInstallments;
IF(#remaining < #periodicDeduction) THEN
SET #loanDeduction = #remaining;
ELSE
SET #loanDeduction = #periodicDeduction;
END IF;
END IF;
RETURN #loanDeduction;
END;//
DELIMITER ;
If I call it like this, it works fine:
SELECT fn_computeLoanAmortization(3, 4)
But if I call it inside a SELECT statement, the result becomes erroneous:
SELECT Id, fn_computeLoanAmortization(Id, 4) AS Amort FROM emp_table
There's only one entry in the loans_table and the above statement should only result with one row having value in the Amort column but there are lots of random rows with the same Amort value as the one with the matching entry, which should not be the case.
Have anyone met this kind of weird dilemma? Or I might have done something wrong from my end. Kindly enlighten me.
Thank you very much.
EDIT:
By erroneous, I meant it like this:
loans_table has one record
EmpId = 1
TypeId = 2
PeriodicDeduction = 100
TotalAmount = 1000
TotalInstallments = 200
DeductionFlag = 1
emp_table has several rows
EmpId = 1
Name = Paolo
EmpId = 2
Name = Nikko
...
EmpId = 5
Name = Ariel
when I query the following statements, I get the correct value:
SELECT fn_computeLoanAmortization(1, 2)
SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table WHERE EmpId = 1
But when I query this statement, I get incorrect values:
SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table
Resultset would be:
EmpId | Amort
--------------------
1 | 100
2 | 100 (this should be 0, but the query returns 100)
3 | 100 (same error here)
...
5 | 100 (same error here up to the last record)
Inside your function, the variables you use to retrieve the values from the loans_table table are not local variables local to the function but session variables. When the select inside the function does not find any row, those variables still have the same values as from the previous execution of the function.
Use real local variables instead. In order to do that, use the variables names without # as a prefix and declare the variables at the beginning of the function. See this answer for more details.
I suspect the problem is that the variables in the INTO are not re-set when there is no matching row.
Just set them before the INTO:
BEGIN
SET #loanDeduction = 0.00;
SET #totalAmount = 0;
SET #periodicDeduction = 0;
SET #totalInstallments = 0;
SET #deductionFlag = 0;
SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
. . .
You might just want to set them to NULL.
Or, switch your logic to use local variables:
SET v_loanDeduction = 0.00;
SET v_totalAmount = 0;
SET v_periodicDeduction = 0;
SET v_totalInstallments = 0;
SET v_deductionFlag = 0;
And so on.
I'm trying to make my first function, it creates without any error, but, when I try to use it it gives me error.
Here's the function -
CREATE FUNCTION isie_kontakti (condition CHAR(3))
RETURNS CHAR(100)
BEGIN
DECLARE returnthis CHAR(100);
SELECT DISTINCT Person.name, Person.lastName, Contacts.mobile, Contacts.email
FROM Person JOIN Contacts on Contacts.Person_ID = Person.ID
JOIN ParentChild on ParentChild.parentID = Person.ID
JOIN ChildGroup ON ChildGroup.Person_ID = ParentChild.childID
WHERE ChildGroup.Group_ID = 'condition' INTO returnthis;
RETURN returnthis;
END//
Table schema - http://www.imagesup.net/dm-713886347846.png
You create your function to return a single column of type char(100) yet the returnthis item contains quite a few columns.
You need to match up your query and return type.
How you do that depends on what you're trying to achieve. It's possibly as simple as just concatenating the columns from the select into a single variable, something along the lines of (untested since I don't have my DBMS available at the moment):
SELECT Person.name | ' '
| Person.lastName | ' '
| Contacts.mobile | ' '
| Contacts.email
FROM ...