Server Error in '/' Application Cannot convert a char value to money - asp.net

I am running the following stored precedure.
The result set is binded on a gridView control.
#EmbossLine varchar(20),
#TransactionTypeID int,
#DateFrom datetime,
#DateTo datetime
AS
Select
pt.TransactionDate,
m.MerchantName1,
pt.TerminalID,
pt.SequenceNumber,
tt.TransactionType,
case TT.TransactionTypeID when 0 then PT.TotalAmount else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then PT.TotalAmount else 'null' end 'PointsRedemeed'
from POS_Transactions PT
inner join TransactionType TT on TT.TransactionTypeID = PT.TransactionTypeID
inner join CardBalance CB on CB.PAN = PT.PAN
inner join Terminal T on T.TerminalID = PT.TerminalID
inner join Merchant M on M.MerchantID = T.MerchantID
where
(PT.TransactionDate>=#DateFrom and PT.TransactionDate<=#DateTo)
and (PT.TransactionTypeID = #TransactionTypeID or #TransactionTypeID ='-999')
and(PT.PAN=#EmbossLine or PT.PAN='-999')
order by PT.TransactionDate desc
Actually what Im trying to do is, I want to print null whenever my TransactionTypeID is not equal to 0 or 2. but it throws a runtime exception
Cannot convert a char value to money. The char value has incorrect syntax.
I know it is a conversion issue and want to know how can I print some value when my conditions evaluates to false

Change these two lines:
case TT.TransactionTypeID when 0 then PT.TotalAmount else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then PT.TotalAmount else 'null' end 'PointsRedemeed'
to this:
case TT.TransactionTypeID when 0 then PT.TotalAmount else null end 'PointsEarned',
case TT.TransactionTypeID when 2 then PT.TotalAmount else null end 'PointsRedemeed'
You want to produce a null value in your else condition. You are currently producing the word 'null' which is where the conversion is failing - you can't convert the word (char data type) 'null' to the money datatype.
EDIT:
You will need to cast the values to a string to do this. But that would mean instead of returning the money datatype to your client, you would be returning a string.
This sort of thing should really be handled in the client and not in SQL Server. In anycase try this to convert everything to a string:
case TT.TransactionTypeID when 0 then Cast(PT.TotalAmount as varchar(50)) else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then Cast(PT.TotalAmount as varchar(50)) else 'null' end 'PointsRedemeed'

Do this.
case TT.TransactionTypeID when 0 then cast(PT.TotalAmount as varchar) else 'null' end 'PointsEarned',
case TT.TransactionTypeID when 2 then cast(PT.TotalAmount as varchar) else 'null' end 'PointsRedemeed'
just cast TotalAmount to varchar, it should work.

Related

Simple if else statement is not working in MariaDB

Update:
I want to insert data conditionally
Why this MariaDB query has errors:
if 2 > 1 then
select 'hi'
else
select 'bye'
end if
This is the error:
Error in query (1064): Syntax error near 'else select 'bye' end if' at line 3
if (exists (select * from teachers where name = 'Jennifer'))
then
-- do nothing
else
insert into teachers (name, age)
values ('Jennifer', 30)
end if;
I'm not sure that IF can be used like this outside of a stored procedure or function. You may use the IF() function or a CASE expression instead:
SELECT IF(2 > 1, 'hi', 'bye')
OR
SELECT CASE WHEN 2 > 1 THEN 'hi' ELSE 'bye' END

Using cursors in loop in PL/SQL

I have table that contains 3 column.First column name is id , second column's name is parent_id and third one is expression.What i want to do is to search expression column for id.For example I send id value then if parent_id column has a value I want to send parent_id value and want to check expression column has 'E' or not.If It has null value and result has parent_id then I want to send parent_id value and again I want to check expression column has 'E' or not.If expression column has a value like that 'E', I updated variable resultValue as 1 and end loop.
my table A : It should return resultValue =1
id |parent_id|expression
123 |null | null
45 |123 | 'E'
22 |45 | null
my table B : It should return resultValue = 0
id |parent_id|expression
30 |null | null
20 |30 | null
10 |20 | null
my table C : It should return resultValue = 0
id |parent_id|expression
30 |null | null
20 |30 | null
10 |null | null
If first sending id(10) does not contain parent_id(table C) resultValue variable should be 0. If I find 'E' expression any parent row resultValue variable should return 1.
I created a code block with cursor.For the first time I used cursor.I am not sure using cursor with this kind of problem is a good idea or not.My code is running but to open cursor then to close cursor then again opening cursor it is good idea?
DECLARE
resultValue NUMBER := 0;
CURSOR c(v_id NUMBER )
IS
SELECT id_value, id_parent, expression FROM students WHERE id_value = v_id;
PROCEDURE print_overpaid
IS
id_value NUMBER;
id_parent NUMBER;
expression VARCHAR2(20);
BEGIN
LOOP
FETCH c INTO id_value, id_parent, expression;
EXIT
WHEN c%NOTFOUND;
IF id_parent IS NULL AND expression IS NULL THEN
EXIT;
END IF;
IF id_parent IS NOT NULL THEN
CLOSE c;
OPEN c(id_parent);
ELSIF id_parent <> NULL AND expression = 'X' OR id_parent IS NULL AND expression = 'X' THEN
resultValue := 1;
EXIT;
END IF;
END LOOP;
END print_overpaid;
BEGIN
OPEN c(22);
print_overpaid;
DBMS_OUTPUT.PUT_LINE(' My resultValue is : ' || resultValue);
CLOSE c;
END;
If I understood your description correctly, you are looking to see it the specified id of any row in the parentage contains 'E' in the column expression. You are correct that closing and reopening a cursor is not really a good idea. Although I do like your use of a nested procedure. However, it's not really necessary as this can be solved with a single query. The approach will be a recursive CTE that checks the target row for 'E' until a row contains it or the row does not have a parent.
with search_for_e(id, parent_id, e_cnt) as
( select id, parent_id, case when expression = 'E' then 1 else 0 end
from exp_tbl
where id = &id
union all
select t.id,t.parent_id, case when t.expression = 'E' then 1 else 0 end
from search_for_e s
join exp_tbl t on (t.id = s.parent_id)
where t.parent_id is not null
and s.e_cnt = 0
)
select max(e_cnt)
from search_for_e;
See fiddle here, it also contains an anonymous block implementation with nested function and one with cursor.

Conversion failed when converting the nvarchar value 'B' to data type int

Getting this error when ever I tried to execute the entire procedure. Below is the piece of code from the procedure.
SELECT
DISTINCT SUBSTRING (a.GL06001,19,10) as ProjectNo,
--PR01040 UD_10,
SUBSTRING (a.GL06001,1,8) as AccountNo,
a.GL06002 as TransNo,
a.GL06004 as TransAmount,
a.GL06003 as TransDate,
a.GL06005 as TransDesc,
'GL' as SourceType,
' ' as ResourceCode,
' ' as TransLine,
0 as CostPR,
'000000' as PRTransNo,
a.GL06027 as SubprojNo,
a.GL06028 as ActiLineNo,
a.GL06012 as TransType,
a.GL06016 as Counter
from ScalaMX.dbo.GL06PA17 a where a.GL06003 between '2017-02-21 00:00:00.000' and '2017-03-01 00:00:00.000'
There are actually 18000+ rows and 15 columns. Any hint on how to track which column has B value?
I downloaded the result in Excel and ctrl+f 'B' But still no clue and I couldn't find it.
convert into stored procedure, see below sample
declare
n integer;
m integer;
begin
for i in ( select primarykeycolumn, a,b from table )
loop
begin
n := i.a;
m := i.b;
exception
when others then
dbms_output.put_line(i.primarykeycolumn);
end
end loop;
end;
When conversion error happens it will catch the exception hence find the primary key.

ExecuteScalar not passing the right parameter. always returns 0

I' so lost.... This is my stored proc:
#User_ID INT,
#Form_NAME NVARCHAR(25)
AS
BEGIN
DECLARE #Count int = 0
DECLARE #myReturnCode INT
SELECT #Count = COUNT (tblForms.Form_Name)
FROM tblForms INNER JOIN
tblForms_Roles_MTM ON tblForms.Form_Id = tblForms_Roles_MTM.Form_Id INNER JOIN
tblRoles ON tblForms_Roles_MTM.Role_Id = tblRoles.Role_Id INNER JOIN
tblUsers_Roles_MTM ON tblRoles.Role_Id = tblUsers_Roles_MTM.Role_Id
WHERE (tblUsers_Roles_MTM.User_Id = #User_ID AND tblForms.Form_Name = #Form_NAME)
IF #Count = 0
BEGIN SET #myReturnCode = 0 END
ELSE
BEGIN SET #myReturnCode = 1 END
SELECT #myReturnCode as ReturnCode
END
In my code behind I call the procedure passing the 2 params and then :
...
con.Open();
int ReturnCode = (int)cmd.ExecuteScalar();
Response.Write(ReturnCode);
But myReturnCode is always 0.
When I execute the proc in SSMS is I see in "results" 2 values :
I guess that ExecuteScalar is returning the value of "Return Value".
So how do I get the value of "ReturnCode"?
I've been googling it for the past 36 hours. The answer is probably out there but....where? Couldn't find it.
Any hint will be greatly appreciated.
(Win-7 , SS-2014 , VS-2013)
My sincere apologies.... Data in one of the tables was invalid. The procedure never found what it was meant to find, therefore it always returned 0. The stored procedure and the code are just fine. Fixing the data in that table solved my problem.
I am so ashamed.... Now how do I kill this question? It is just white noise in this forum.

Why can't I compare an empty string? [duplicate]

I have the following Oracle PL/SQL codes that may be rusty from you guys perspective:
DECLARE
str1 varchar2(4000);
str2 varchar2(4000);
BEGIN
str1:='';
str2:='sdd';
IF(str1<>str2) THEN
dbms_output.put_line('The two strings is not equal');
END IF;
END;
/
This is very obvious that two strings str1 and str2 are not equal, but why 'The two strings are not equal' was not printed out? Do Oracle have another common method to compare two string?
As Phil noted, the empty string is treated as a NULL, and NULL is not equal or unequal to anything. If you expect empty strings or NULLs, you'll need to handle those with NVL():
DECLARE
str1 varchar2(4000);
str2 varchar2(4000);
BEGIN
str1:='';
str2:='sdd';
-- Provide an alternate null value that does not exist in your data:
IF(NVL(str1,'X') != NVL(str2,'Y')) THEN
dbms_output.put_line('The two strings are not equal');
END IF;
END;
/
Concerning null comparisons:
According to the Oracle 12c documentation on NULLS, null comparisons using IS NULL or IS NOT NULL do evaluate to TRUE or FALSE. However, all other comparisons evaluate to UNKNOWN, not FALSE. The documentation further states:
A condition that evaluates to UNKNOWN acts almost like FALSE. For example, a SELECT statement with a condition in the WHERE clause that evaluates to UNKNOWN returns no rows. However, a condition evaluating to UNKNOWN differs from FALSE in that further operations on an UNKNOWN condition evaluation will evaluate to UNKNOWN. Thus, NOT FALSE evaluates to TRUE, but NOT UNKNOWN evaluates to UNKNOWN.
A reference table is provided by Oracle:
Condition Value of A Evaluation
----------------------------------------
a IS NULL 10 FALSE
a IS NOT NULL 10 TRUE
a IS NULL NULL TRUE
a IS NOT NULL NULL FALSE
a = NULL 10 UNKNOWN
a != NULL 10 UNKNOWN
a = NULL NULL UNKNOWN
a != NULL NULL UNKNOWN
a = 10 NULL UNKNOWN
a != 10 NULL UNKNOWN
I also learned that we should not write PL/SQL assuming empty strings will always evaluate as NULL:
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.
Let's fill in the gaps in your code, by adding the other branches in the logic, and see what happens:
SQL> DECLARE
2 str1 varchar2(4000);
3 str2 varchar2(4000);
4 BEGIN
5 str1:='';
6 str2:='sdd';
7 IF(str1<>str2) THEN
8 dbms_output.put_line('The two strings is not equal');
9 ELSIF (str1=str2) THEN
10 dbms_output.put_line('The two strings are the same');
11 ELSE
12 dbms_output.put_line('Who knows?');
13 END IF;
14 END;
15 /
Who knows?
PL/SQL procedure successfully completed.
SQL>
So the two strings are neither the same nor are they not the same? Huh?
It comes down to this. Oracle treats an empty string as a NULL. If we attempt to compare a NULL and another string the outcome is not TRUE nor FALSE, it is NULL. This remains the case even if the other string is also a NULL.
I compare strings using = and not <>. I've found out that in this context = seems to work in more reasonable fashion than <>. I have specified that two empty (or NULL) strings are equal. The real implementation returns PL/SQL boolean, but here I changed that to pls_integer (0 is false and 1 is true) to be able easily demonstrate the function.
create or replace function is_equal(a in varchar2, b in varchar2)
return pls_integer as
begin
if a is null and b is null then
return 1;
end if;
if a = b then
return 1;
end if;
return 0;
end;
/
show errors
begin
/* Prints 0 */
dbms_output.put_line(is_equal('AAA', 'BBB'));
dbms_output.put_line(is_equal('AAA', null));
dbms_output.put_line(is_equal(null, 'BBB'));
dbms_output.put_line(is_equal('AAA', ''));
dbms_output.put_line(is_equal('', 'BBB'));
/* Prints 1 */
dbms_output.put_line(is_equal(null, null));
dbms_output.put_line(is_equal(null, ''));
dbms_output.put_line(is_equal('', ''));
dbms_output.put_line(is_equal('AAA', 'AAA'));
end;
/
To fix the core question, "how should I detect that these two variables don't have the same value when one of them is null?", I don't like the approach of nvl(my_column, 'some value that will never, ever, ever appear in the data and I can be absolutely sure of that') because you can't always guarantee that a value won't appear... especially with NUMBERs.
I have used the following:
if (str1 is null) <> (str2 is null) or str1 <> str2 then
dbms_output.put_line('not equal');
end if;
Disclaimer: I am not an Oracle wizard and I came up with this one myself and have not seen it elsewhere, so there may be some subtle reason why it's a bad idea. But it does avoid the trap mentioned by APC, that comparing a null to something else gives neither TRUE nor FALSE but NULL. Because the clauses (str1 is null) will always return TRUE or FALSE, never null.
(Note that PL/SQL performs short-circuit evaluation, as noted here.)
I've created a stored function for this text comparison purpose:
CREATE OR REPLACE FUNCTION TextCompare(vOperand1 IN VARCHAR2, vOperator IN VARCHAR2, vOperand2 IN VARCHAR2) RETURN NUMBER DETERMINISTIC AS
BEGIN
IF vOperator = '=' THEN
RETURN CASE WHEN vOperand1 = vOperand2 OR vOperand1 IS NULL AND vOperand2 IS NULL THEN 1 ELSE 0 END;
ELSIF vOperator = '<>' THEN
RETURN CASE WHEN vOperand1 <> vOperand2 OR (vOperand1 IS NULL) <> (vOperand2 IS NULL) THEN 1 ELSE 0 END;
ELSIF vOperator = '<=' THEN
RETURN CASE WHEN vOperand1 <= vOperand2 OR vOperand1 IS NULL THEN 1 ELSE 0 END;
ELSIF vOperator = '>=' THEN
RETURN CASE WHEN vOperand1 >= vOperand2 OR vOperand2 IS NULL THEN 1 ELSE 0 END;
ELSIF vOperator = '<' THEN
RETURN CASE WHEN vOperand1 < vOperand2 OR vOperand1 IS NULL AND vOperand2 IS NOT NULL THEN 1 ELSE 0 END;
ELSIF vOperator = '>' THEN
RETURN CASE WHEN vOperand1 > vOperand2 OR vOperand1 IS NOT NULL AND vOperand2 IS NULL THEN 1 ELSE 0 END;
ELSIF vOperator = 'LIKE' THEN
RETURN CASE WHEN vOperand1 LIKE vOperand2 OR vOperand1 IS NULL AND vOperand2 IS NULL THEN 1 ELSE 0 END;
ELSIF vOperator = 'NOT LIKE' THEN
RETURN CASE WHEN vOperand1 NOT LIKE vOperand2 OR (vOperand1 IS NULL) <> (vOperand2 IS NULL) THEN 1 ELSE 0 END;
ELSE
RAISE VALUE_ERROR;
END IF;
END;
In example:
SELECT * FROM MyTable WHERE TextCompare(MyTable.a, '>=', MyTable.b) = 1;
Only change the line
str1:='';
to
str1:=' ';
The '' would be treated as NULL, so, both the strings need to be checked as NULL.
Function:
CREATE OR REPLACE FUNCTION str_cmpr_fnc(str_val1_in IN VARCHAR2, str_val2_in IN VARCHAR2) RETURN VARCHAR2
AS
l_result VARCHAR2(50);
BEGIN
-- string comparison
CASE
WHEN str_val1_in IS NULL AND str_val2_in IS NULL THEN
l_result := 'Both Unknown';
WHEN str_val1_in IS NULL THEN
l_result := 'Str1 Unknown';
WHEN str_val2_in IS NULL THEN
l_result := 'Str2 Unknown';
ELSE
CASE
WHEN str_val1_in = str_val2_in THEN
l_result := 'Both are equel';
ELSE
l_result := 'Both strings are not equal';
END CASE;
END CASE;
-- return result
RETURN l_result;
EXCEPTION
WHEN OTHERS THEN
-- set serveroutput on to get the error information
DBMS_OUTPUT.put_line(SQLERRM||' ,'|| DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
-- return result
RETURN l_result;
END str_cmpr_fnc;
Sql Statement:
SELECT str_cmpr_fnc('7', 'd') FROM DUAL;
To the first question:
Probably the message wasn't print out because you have the output turned off. Use these commands to turn it back on:
set serveroutput on
exec dbms_output.enable(1000000);
On the second question:
My PLSQL is quite rusty so I can't give you a full snippet, but you'll need to loop over the result set of the SQL query and CONCAT all the strings together.

Resources