SQL Join only on condition? - mysql

I have about 10 different sql statements that update different tables. They look similar to this:
Update Y
SET x = n
Where something = #somevar
Now I need to Update only certain rows when the #hasRows var is set. I could simply do this:
if not #hasRows is null
begin
Update Y
SET x = n
from Y inner join #items on y.Item = #items.Item
Where something = #somevar
end
else
begin
Update Y
SET x = n
Where something = #somevar
end
Is there a way to avoid the if/else and do the update in one statement?
I am using SQL2005.

Perhaps something like this: (copypasta your example)
UPDATE Y
SET x = n
FROM Y
WHERE something = #somevar
AND (
(#Items IS NULL)
OR (y.Item = #Item)
)
The JOIN isn't used but it's always proceeding if #items is NULL, or using the intended condition.
Problem here is that your example seems to include a TVP #ITEMS but TVPs don't exist in SQLServer2k5? So whatever the value is should be placed in the parameter.
Alternatively, if #Table exists but has no rows you can do this:
UPDATE Y
SET x = n
FROM Y
JOIN #Items ON (#HasRows = 0) OR (#Items.Item = Y.Item)
WHERE something = #somevar
If you don't know whether or not #Items IS NULL then your condition is your option because declared variables are resolved before the statement is executed.

Related

User variable is giving last assigned values in a Session

We recently found the re-declaration issue in Mysql. If the query or procedure is called repeatedly in loop it retained last values.
SET #ToolType = 'test-Tool1';
SET #ToolType = (select Tool_type from IBP__Tool_type aa inner join IBP__xTool_set bb on aa.Tool_type_id=-1) ;
select #ToolType;
SET #ToolType = 'test-Tool1';
select #ToolType:=Tool_type from IBP__Tool_type aa inner join IBP__xTool_set bb on aa.Tool_type_id=-1;
select #ToolType; -- = OR :=
SET #ToolType = 'test-Tool2';
select Tool_type into #ToolType from IBP__Tool_type aa inner join IBP__xTool_set bb on aa.Tool_type_id=-1;
select #ToolType;
Above code will have Results : (when -1 is not present in tables so the output should be null in all cases)
null
test-tool1
test-tool2
what is the best way to resolve This Issue.
assign the variable to null before using it each time in query. User Session issues will always store the variable value in Mysql server and cause these issues.
SET #ToolType = null;

How to update value in MySQL when the stored version differs to the passed argument

UPDATE table SET x = :x, y = :y, z = IF(x <> :x, NOW(), z);
I need to check whether value of the old "x" is different from the new "x". I can't do that within the IF statement as shown above because value of x is already changed so it equals to the :x.
Basically, what I am trying to do is something like:
IF(oldX <> :newX) THEN NOW() ELSE NO CHANGE;
Is there any way how to achieve that or am I better doing this using a subquery or a variable? *I definitely prefer executing one query only.
MySQL does not support the standard on this:
The second assignment in the following statement sets col2 to the
current (updated) col1 value, not the original col1 value. The result
is that col1 and col2 have the same value. This behavior differs from
standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
So, the following works in a simple example in SQL Fiddle:
UPDATE table
SET x = if (#x := x, :x, :x),
y = :y,
z = IF(x <> #x, NOW(), z);
It should also work if you reverse the order:
UPDATE table
SET z = IF(x <> :x, NOW(), z),
x = :x,
y = :y;
The documentation says that single table updates are "generally" processed in lexical order.

In SQL, is there something like: WHERE x = ANY_VALUE?

In a SQL query like this:
SELECT *
FROM MyTable
WHERE x = 5;
is it possible to modify the WHERE condition so that SELECT looks for every value of x? Something like (wrong syntax):
SELECT *
FROM MyTable
WHERE x = ANY_VALUE;
The reason behind this question is that I have to parse and modify some SQL queries through some C++ code I am writing. I know in this case I could just remove or comment the whole WHERE condition, but this is a simplification.
Thank you.
In cases like this, you normally would do something like this:
SELECT *
FROM MyTable
WHERE x = SOME_VALUE OR 1 = 1;
SOME_VALUE is arbitrary, it can be anything matching the type of the column, because the WHERE clause will always be true because of the second part.
You could just omit WHERE clause. :)
While I think it's really the wrong way to go about it (just make the effort to remove the Where), how about where x = x? It won't work if X is null (you'd have to use "x is null or x = x") but don't bother if you know x won't be null.
You can try that:
SELECT *
FROM MyTable
WHERE x = x OR x IS NULL;
You could make your query like this
DECLARE #VALUE as (type of x)
--SET #VALUE = ''
SELECT *
FROM MyTable
WHERE (#VALUE IS NULL OR x = #VALUE);
and your parse would only have to replace
the: --SET #VALUE = '' line for one with the value you want, minus the comment, like: SET #VALUE = 'abc'
hope this helps

SQL Server 2008: Error converting data type nvarchar to float

Presently troubleshooting a problem where running this SQL query:
UPDATE tblBenchmarkData
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
WHERE
FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID FROM tblZEGCode
WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Results in the following error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.
The really odd thing is, if I change the UPDATE to SELECT to inspect the values that are retrieved are numerical values:
SELECT DataValue
FROM tblBenchmarkData
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID
FROM tblZEGCode WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Here are the results:
DataValue
2285260
1205310
Would like to use TRY_PARSE or something like that; however, we are running on SQL Server 2008 rather than SQL Server 2012. Does anyone have any suggestions? TIA.
It would be helpful to see the schema definition of tblBenchmarkData, but you could try using ISNUMERIC in your query. Something like:
SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335
ELSE 0 END
Order of execution not always matches one's expectations.
If you set a where clause, it generally does not mean the calculations in the select list will only be applied to the rows that match that where. SQL Server may easily decide to do a bulk calculation and then filter out unwanted rows.
That said, you can easily write try_parse yourself:
create function dbo.try_parse(#v nvarchar(30))
returns float
with schemabinding, returns null on null input
as
begin
if isnumeric(#v) = 1
return cast(#v as float);
return null;
end;
So starting with your update query that's giving an error (please forgive me for rewriting it for my own clarity):
UPDATE B
SET
OriginalValue = DataValue,
OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
I think you'll find that a SELECT statement with exactly the same expressions will give the same error:
SELECT
OriginalValue,
DataValue NewOriginalValue,
OriginalUnitID,
DataUnitID OriginalUnitID,
DataValue,
CAST(DataValue AS float) * 1.335 NewDataValue
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
This should show you the rows that can't convert:
SELECT
B.*
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
AND IsNumeric(DataValue) = 0
-- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work
The trick in the last commented line is to tack on things to the string to force only valid numbers to be numeric. For example, if you wanted only integers, IsNumeric(DataValue + '.0E0') = 0 would show you those that aren't.

Update Field When Not Null

I have an update statement that updates fields x, y and z where id = xx.
In the table I have a few different x_created_datetime fields (for different portions of the record that are maintained/entered by different folks). I'd like to write a single query that will update this field if is null, but leave it alone if is not null.
So what I have is:
UPDATE newspapers
SET scan_notes = "data",
scan_entered_by = "some_name",
scan_modified_date = "current_unix_timestamp"
WHERE id = X
What I need is a way to add in the following, but still always update the above:
scan_created_date = "current_unix_timestamp"
where scan_created_date is null
I'm hoping I can do this without a second transaction to the DB. Any ideas on how to accomplish this?
Do this:
UPDATE newspapers
SET scan_notes = "data",
scan_entered_by = "some_name",
scan_modified_date = "current_unix_timestamp",
scan_created_date = COALESCE(scan_created_date, "current_unix_timestamp")
WHERE id = X
The COALESCE function picks the first non-null value. In this case, it will update the datestamp scan_created_date to be the same value if it exists, else it will take whatever you replace "current_unix_timestamp" with.
mySQL has an IFNULL function, so you could do:
UPDATE newspapers
SET scan_notes = "data",
scan_entered_by = "some_name",
scan_modified_date = "current_unix_timestamp"
scan_created_date = IFNULL( scan_created_date, "current_unix_timestamp" )
WHERE id = X
I think that what you're looking for is IF()
UPDATE newspapers
SET scan_notes = "data",
scan_entered_by = "some_name",
scan_modified_date = "current_unix_timestamp",
scan_created_date = IF(scan_created_date IS NOT NULL, "current_unix_timestamp", NULL)
WHERE id = X
You could use COALESCE() wich returns the first NON-NULL value):
scan_created_date = COALESCE(scan_created_date, "current_unix_timestamp")
You can do something like this:
UPDATE newspapers a, newspapers b
SET a.scan_notes = "data",
a.scan_entered_by = "some_name",
a.scan_modified_date = "current_unix_timestamp",
b.scan_created_date = "current_unix_timestamp"
WHERE a.id = X AND b.id = X AND b.scan_created_date is not NULL
Its like equivalent to Oracle's NVL.
You can use it like below in a prepared statement using parameters
UPDATE
tbl_cccustomerinfo
SET
customerAddress = COALESCE(?,customerAddress),
customerName = COALESCE(?,customerName),
description = COALESCE(?,description)
WHERE
contactNumber=?