"Subquery returns more than 1 row" when use select to set value of parameter - sql

I have an issue when I try to set the value of a variable with a subquery.
This is my SQL code:
SELECT #V_SOURCE = (SELECT ITEM_SOURCE
FROM TABLE1
WHERE OPP_CODE = #V_OPP_CODE
AND PDGROUPNO = #V_PRD_GROUP_NO
AND DELETE_FLAG IS NULL
AND CONTRACTOR = #V_CONTRACTOR
AND OPP_ITEM_NO = #_OPP_ITEM_NO)
When I run this code with an assumed variable that is used in WHERE condition, it returns only 1 row and 1 col that is correct but if I run this code with store procedure it will return the error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <=, >, >= or when the subquery is used as an expression

The sub-query can return multiple rows.
Even if it shouldn't, that won't do.
But you can change it to this.
SELECT #V_SOURCE = ITEM_SOURCE
FROM TABLE1
WHERE OPP_CODE = #V_OPP_CODE
AND PDGROUPNO = #V_PRD_GROUP_NO
AND DELETE_FLAG IS NULL
AND CONTRACTOR = #V_CONTRACTOR
AND OPP_ITEM_NO = #_OPP_ITEM_NO
GROUP BY ITEM_SOURCE;
It'll assign the last value of the resultset to the variable.
Which is fine, since you expect only one anyway.
Another way is to pick only the top 1
SET #V_SOURCE = (
SELECT TOP 1 ITEM_SOURCE
FROM TABLE1
WHERE OPP_CODE = #V_OPP_CODE
AND PDGROUPNO = #V_PRD_GROUP_NO
AND DELETE_FLAG IS NULL
AND CONTRACTOR = #V_CONTRACTOR
AND OPP_ITEM_NO = #_OPP_ITEM_NO
);

I find an issue in my query because of I query data to use for this query some CONTRACTOR is NULL then it makes an error when using this query
SELECT #V_SOURCE = (SELECT ITEM_SOURCE
FROM TABLE1
WHERE OPP_CODE = #V_OPP_CODE
AND PDGROUPNO = #V_PRD_GROUP_NO
AND DELETE_FLAG IS NULL
AND CONTRACTOR = #V_CONTRACTOR
AND OPP_ITEM_NO = #_OPP_ITEM_NO)
When I filter data that CONTRACTOR is NULL out, I don't get any error now.

Related

isnull with AND : -An expression of non-boolean type specified in a context where a condition is expected, near 'and'

I am tryng to use isnull with AND operator
SELECT *
FROM contacts AS cont
LEFT JOIN contactphones AS contPhone
ON cont.contactid = contPhone.contactid
LEFT JOIN sys_phonetypedesc AS phont
ON phont.typeid = contPhone.phonetype
LEFT JOIN salutations AS tsal
ON tsal.salutid = cont.salutation
WHERE cont.contactid = '29'
AND ( Isnull(phont.typedesc, 1) )
AND ( Isnull(contPhone.phonenum, 1) )
ORDER BY phont.typedesc
but got following error
An expression of non-boolean type specified in a context where a
condition is expected, near 'and'.
I also tried using the case statement
SELECT *
FROM contacts AS cont
LEFT JOIN contactphones AS contphone
ON cont.contactid = contphone.contactid
LEFT JOIN sys_phonetypedesc AS phont
ON phont.typeid = contphone.phonetype
LEFT JOIN salutations AS tsal
ON tsal.salutid = cont.salutation
WHERE cont.contactid = '29'
AND (
CASE
WHEN phont.typedesc = NULL THEN 1
ELSE phont.typedesc
END as a)
but it is not working. I am looking for ifnull logic in MSSQL but case and if else not working correctly
please suggest
I don't think you need to use ISNULL() here, instead you are looking for IS NULL/IS NOT NULL. First let's see why you get this error message
An expression of non-boolean type specified in a context where a condition is expected, near 'and'.
You get this error because ( Isnull(phont.typedesc, 1) ) is not a boolean expression and that what the WHERE clause needs (True or False).
eg: Let's assume phont IS NULL, then ISNULL() will return 1, so you are writing cont.contactid = '29' AND 1 AND ....
What should I do then to get ride of this error?
Just make it a boolean expression as Isnull(phont.typedesc, 1) = 1 or what ever you want instead of =1, it maybe other too because it's not clear what you need to check.
Now, the use of ISNULL() as I seeis point less, cause the possible cases I can see is like the follow:
Isnull(phont.typedesc, 1) = 1 then directly phont IS NULL.
Isnull(phont.typedesc, 1) <> 1 then directly phont IS NOT NULL.
Isnull(phont.typedesc, 1) = AnyValue then why not directly phont = value or phont IN(<Values>) if you are looking for more than 1 value.
You're not comparing the result of isnull to anything in your where clause.
(isnull(phont.TypeDesc,1))
gives you either the TypeDesc, or if it's null gives you 1, but then you move directly onto an AND statement. In other words, if all relevant fields are null, what you'd be trying to do is:
where cont.ContactID = '29' and 1 and 1
You either have the isnull in the wrong place (if you want see it in your selected fields), or you forgot to compare it to something.
If you want to select rows where those fields are actually null then what you want is:
where cont.ContactID = '29'
and phont.TypeDesc is null
and contPhone.PhoneNum is null
select * from contacts as cont left join ContactPhones as contPhone on cont.ContactID=contPhone.ContactID
left join SYS_PhoneTypeDesc as phont on
phont.TypeID = contPhone.PhoneType
left join SALUTATIONS as tsal on tsal.salutid = cont.Salutation where cont.ContactID = '29' and (isnull(phont.TypeDesc,1))=check what u want here
and (isnull(contPhone.PhoneNum,1))=check what u want here enter code here
order by
phont.TypeDesc
Isnull(contPhone.phonenum,1) return 1 when your contPhone.phonenum value will be null else it will return that column value but the point is you got error because you have not used any comparison value as a result it thrown error
Your condition will be like below
Where contactId=29 and isnull(phonenum,1)= // any value

How to give change working of having function dynamicaly on executing an sql statement?

I'm having a Sql code like as follows
Select a.ItemCode, a.ItemDesc
From fn_BOM_Material_Master('A', #AsOnDate, #RptDate, #BranchID, #CompID)a
Left Outer Join fn_INV_AsOnDate_Stock(#StockDate, #AsOnDate, #RptDate, #BranchID, #CompID, #Finyear)b
On a.ItemCode=b.ItemCode and b.WarehouseCode<>'WAP'
and a.BranchID=b.BranchID and a.CompID=b.COmpID
Where a.ItemNatureCode = 'F' and a.BranchID = #BranchID and a.CompID = #CompID
Group by a.ItemCode, a.ItemDesc
Having sum(b.CBQty)<=0
Here the problem is that im passing an "#ShowZeroStock" value as as bit if the "#ShowZeroStock" value is '1' then Having should not be validated or (i.e: All values from the table should be returned including zero)
So How to change the query based on passed bit value "#ShowZeroStock"
I can Use "If else " condition at the top and remove having in else part, but for a lengthy query i can't do the same.
Is this the logic you want?
Having sum(b.CBQty) <= 0 or #ShowZeroStock = 1

Subquery returned more than one value... in sql query, What that means?, and what is wrong?

Why I got this message if the query seems right:
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
" But when I try the query splitted it works fine, I mean, what could happen?
and this is the query :
UPDATE llantas_dictamen_scrap
SET clave_operador =
(SELECT REPLACE(scrap, '-', '') as clave_operador
FROM (SELECT RIGHT(clave_operador, CHARINDEX('-',REVERSE(clave_operador), 1)) as scrap
FROM llantas_dictamen_scrap) t
)
Of course I'm returning more than one one value, What that supposed to mean?
UPDATE llantas_dictamen_scrap
SET clave_operador = RIGHT(clave_operador, CHARINDEX('-',REVERSE(clave_operador), 1) -1)
WHERE CHARINDEX('-',clave_operador, 1) > 0
This one adjusts the position of the call to RIGHT, excluding the '-' we found. There's no need to make a call to REPLACE, because once we know the position of the last trailing '-' , we can just excluding by taking the right-most characters (-1 for its position).
You can't return multiple values for a single row. You are updating multiple rows, yes, for FOR EACH ROW, you are giving clave_operador a single value.
You are setting a single column value equal to more than one column value. If you want to update using the same query your using you have to specify which column you want to use. If you specify to select top 1... with order by that should give you a usable single subquery result for your update statement.
Well if you have
Table A
Col A Col B Col C
1 2 3
1 2 3
And you try
Update Table A Set Col B = (select 5 union select 6)
We won't know if we need to set Column B to 5 or 6, so we get an error.
You need to make sure your sub query only returns one value, one easy way would be to do the following to your subquery (notice the Top 1).
SELECT Top 1 REPLACE(scrap, '-', '')as clave_operador FROM (SELECT RIGHT(clave_operador, CHARINDEX('-',REVERSE(clave_operador),1))as scrap FROM llantas_dictamen_scrap)t
what that means this message java.lang.ClassNotFoundExeption:com.mysql.jdbc.Driver
and this is my code in jform
private void saveActionPerformed(java.awt.event.ActionEvent evt) {
String Number = txt_idinf.getText();
String Name = txt_Name.getText();
String Birthdate = txt_Birthdate.getText();
String Cas = txt_Cas.getText();
String Helth = txt_Helth.getText();
String Sourc = txt_Sourc.getText();
String Children = txt_Children.getText();
String Adresse = txt_Adresse.getText();
String PhoneNumber = txt_PhoneNumber.getText();
String Demande = txt_Demande.getText();
String Procédurs = txt_Procédurs.getText();
Connection conn = null;
PreparedStatement pstm = null;
try{
Class.forName ("com.myql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost/infocarte","root","root");
pstm = conn.prepareStatement("insert into information values (?,?,?,?,?,?,?,?,?,?,?)");
pstm.setString(1, Number);
pstm.setString(2, Name);
pstm.setString(3, Birthdate);
pstm.setString(4, Cas);
pstm.setString(5, Helth);
pstm.setString(6, Sourc);
pstm.setString(7, Children);
pstm.setString(8, Adresse);
pstm.setString(9, PhoneNumber);
pstm.setString(10, Demande);
pstm.setString(11, Procédurs);
int i = pstm.executeUpdate();
if (i>0){
JOptionPane.showMessageDialog(null, "تم حفظ البيانات");
}
else{
JOptionPane.showMessageDialog(null, "خطأ في حفظ البيانات");
}}
catch(Exception e){
JOptionPane.showMessageDialog(null,e);
}
}

SQL: field = other_field returns false even if they are identical (NULL values)

I have a difficulty because when comparing two fields in a subquery, although the fields are identical i.e. they both have NULL values, the comparison returns a FALSE result
Therfore NULL = NULL is returning FALSE
Now I know that NULLs are supposed to be compared with the IS operator, however when I compare two fields how am I supposed to know they contain a null? I need to compare two fields for identical data both if the values are NULL or not.
Consider this SQL:
SELECT
*
FROM
fts.fts_customers_data_50360001
WHERE
fts.fts_customers_data_50360001.record_type = 15
AND
fts.fts_customers_data_50360001.mid = 103650360001
AND NOT EXISTS
(
SELECT
fts.temp_fees_50360001.record_type
FROM
fts.temp_fees_50360001
WHERE
fts.temp_fees_50360001.record_type = fts.fts_customers_data_50360001.record_type
AND
fts.temp_fees_50360001.merch_id = fts.fts_customers_data_50360001.mid
AND
fts.temp_fees_50360001.fee_curr = fts.fts_customers_data_50360001.currency
AND
fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
AND
fts.temp_fees_50360001.tran_type = fts.fts_customers_data_50360001.fee_type
AND
fts.temp_fees_50360001.area = fts.fts_customers_data_50360001.region
AND
fts.temp_fees_50360001.srvc_type = fts.fts_customers_data_50360001.card_type
);
In the query above,
fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
both have NULL values inside but the comparison returns false .. too bad
ANY IDEAS WOULD BE MUCH APPRECIATED
As the others have pointed out, NULL cannot be compared with NULL.
In Postgres you can shorten your expressions by using the operator IS DISTINCT FROM which is a null-safe replacement for <>. In your case you'd need to use IS NOT DISTINCT FROM to compare for equality (looks a bit the wrong way round but unfortunately there is no corresponding IS EQUAL TO defined in the SQL standard).
From the manual:
Ordinary comparison operators yield null (signifying "unknown"), not true or false, when either input is null. For example, 7 = NULL yields null, as does 7 <> NULL. When this behavior is not suitable, use the IS [ NOT ] DISTINCT FROM constructs:
So, instead of
(fts.temp_fees_50360001.record_type = fts.fts_customers_data_50360001.record_type
OR (fts.temp_fees_50360001.record_type IS NULL
AND fts.fts_customers_data_50360001.record_type IS NULL)
)
you can use:
(fts.temp_fees_50360001.record_type IS NOT DISTINCT FROM fts.fts_customers_data_50360001.record_type)
to handle NULL values automatically. The condition looks a bit strange if you want to compare for equality but it still is quite short.
First of all, use aliases for your tables, your query will be MUCH more readable:
select *
from fts.fts_customers_data_50360001 as d
where
d.record_type = 15 and
d.mid = 103650360001 and
not exists
(
select *
from fts.temp_fees_50360001 as f
where
f.record_type = d.record_type and
f.merch_id = d.mid and
f.fee_curr = d.currency and
f.card_scheme = d.card_scheme and
f.tran_type = d.fee_type and
f.area = d.region and
f.srvc_type = d.card_type
)
As for your question, there's several ways to do this, for example, you can use syntax like this:
...
(
f.card_scheme is null and d.card_scheme is null or
f.card_scheme = d.card_scheme
)
...
Or use coalesce with some value that couldn't be stored in your column:
...
coalesce(f.card_scheme, -1) = coalesce(d.card_scheme, -1)
...
Recently I also like using exists with intersect for this type of comparisons:
...
exists (select f.card_scheme, f.tran_type intersect select d.card_scheme, d.tran_type)
...
Just a side note - you have to be careful when writing queries like this and check query plans to be sure your indexes are used.
In SQL, null is never equal to null. The only way to get a true result for a comparison with null is via the special tests:
IS NULL
IS NOT NULL
In your case, you must cater specifically for the "two nulls" case being considered equal:
AND (fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
OR (fts.temp_fees_50360001.card_scheme IS NULL
AND fts.fts_customers_data_50360001.card_scheme IS NULL)
)
There's no getting around dealing with it (although there are a few variations).
The following inner SELECT works (but I give no guarantee regarding performance):
SELECT
fts.temp_fees_50360001.record_type
FROM
fts.temp_fees_50360001
WHERE
(fts.temp_fees_50360001.record_type = fts.fts_customers_data_50360001.record_type
OR (fts.temp_fees_50360001.record_type IS NULL AND fts.fts_customers_data_50360001.record_type IS NULL))
AND
(fts.temp_fees_50360001.merch_id = fts.fts_customers_data_50360001.mid
OR (fts.temp_fees_50360001.merch_id IS NULL AND fts.fts_customers_data_50360001.mid IS NULL))
AND
(fts.temp_fees_50360001.fee_curr = fts.fts_customers_data_50360001.currency
OR (fts.temp_fees_50360001.fee_curr IS NULL AND fts.fts_customers_data_50360001.currency IS NULL))
AND
(fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
OR (fts.temp_fees_50360001.card_scheme IS NULL AND fts.fts_customers_data_50360001.card_scheme IS NULL))
AND
(fts.temp_fees_50360001.tran_type = fts.fts_customers_data_50360001.fee_type
OR (fts.temp_fees_50360001.tran_type IS NULL AND fts.fts_customers_data_50360001.fee_type IS NULL))
AND
(fts.temp_fees_50360001.area = fts.fts_customers_data_50360001.region
OR (fts.temp_fees_50360001.area IS NULL AND fts.fts_customers_data_50360001.region IS NULL))
AND
(fts.temp_fees_50360001.srvc_type = fts.fts_customers_data_50360001.card_type
OR (fts.temp_fees_50360001.srvc_type IS NULL AND fts.fts_customers_data_50360001.card_type))

Where clause in sql

My sql query is as follows
IF #StatusId = 10
BEGIN
SELECT
*
FROM
Risk AS R
INNER JOIN Statuses AS St ON R.Status_Id=St.Status_Id
WHERE
R.MitigationOwner = COALESCE(#MitigationOwner,R.MitigationOwner)
AND R.RiskFactor = COALESCE(#RiskFactor,R.RiskFactor)
AND R.RiskArea = COALESCE(#RiskArea,R.RiskArea)
AND R.AddedWhen BETWEEN
COALESCE(CONVERT(DATETIME, #StartDate+'00:00:00',120),R.AddedWhen) AND
COALESCE(CONVERT(DATETIME,#EndDate+'23:59:59',120),R.AddedWhen)
END
When I pass only status Id and all other variables are null, then records with NULL MitigationOwner or ModifiedDate are not displayed..
What is wrong in this query?
Use the form:
...
(R.MitigationOwner = #MitigationOwner OR #MitigationOwner IS NULL)
...
This is optimised in SQL Server. COALESCE isn't.
Edit: This does the same as Paul Williams' answer but his answer allows explicit "NULL = NULL" matches. m ylogic is simpler because NULL never equals NULL.
I believe that by ModifiedDate you meant R.AddedWhen
try this:
SELECT
*
FROM
Risk AS R
INNER JOIN Statuses AS St ON R.Status_Id=St.Status_Id
WHERE
(R.MitigationOwner = COALESCE(#MitigationOwner,R.MitigationOwner) OR R.MitigationOwner IS NULL)
AND R.RiskFactor = COALESCE(#RiskFactor,R.RiskFactor)
AND R.RiskArea = COALESCE(#RiskArea,R.RiskArea)
AND (R.AddedWhen BETWEEN
COALESCE(CONVERT(DATETIME, #StartDate+'00:00:00',120),R.AddedWhen) AND
COALESCE(CONVERT(DATETIME,#EndDate+'23:59:59',120),R.AddedWhen) OR R.AddedWhen IS NULL)
If R.MitigationOwner can be null, then your comparison clause:
WHERE
R.MitigationOwner = COALESCE(#MitigationOwner,R.MitigationOwner)
Must be rewritten to handle NULL values:
WHERE
((R.MitigationOwner IS NULL AND #MitigationOwner IS NULL)
OR (R.MitigationOwner = #MitigationOwner))
See this article on Wikipedia about NULL.