Is there a nesting levels limit with expressions used in SSIS packages? - sql-server-2008

Working in SQL Server 2008. My first stab at an SSIS script and I need to emulate some if/then conditional logic written in VB.net. I couldn't find any previous questions dealing with nested conditions in expressions and believe I'm following what I've been able to uncover via google on nested conditions in a derived column.
I'm receiving an error while attempting to use nested conditions in the derived column transformation editor. The error I'm receiving indicates that SSIS could not parse my expression. The actual exception: "Exception from HRESULT: 0xC0204006 (Microsoft.SqlServer.DTSPipelineWrap)"
Questions for which the answers might immediately answer my question (and create a new problem):
is there a nesting levels limit?
can nesting be performed in the condition1 portion of [expression] ? [condition1] : [condition2]
I'll give two snippets, the first is what I'm actually inserting, the second is a more reader-friendly version. Hopefully someone can point out my error.
Not sure that it has bearing, but please note that [BusArea] is a column derived in a previous step.
actual expression:
[BusArea] == "CCC" || [BusArea] == "NBU" || [BusArea] == "CA" ? (ISNULL([CASE_MORG]) or TRIM([CASE_MORG]) == "" ? ( ISNULL([TRX_MORG]) or TRIM([TRX_MORG]) == "" ? NULL(DT_WSTR,50) : [TRX_MORG]) : [CASE_MORG]) : (ISNULL([CASE_AGT]) or TRIM([CASE_AGT]) == "" ? ( ISNULL([TRX_AGT]) or TRIM([TRX_AGT]) == "" ? NULL(DT_WSTR,50) : [TRX_AGT]) : [CASE_AGT])
formatted for easier reading:
[BusArea] == "CCC" || [BusArea] == "NBU" || [BusArea] == "CA" ?
(ISNULL([CASE_MORG]) or TRIM([CASE_MORG]) == "" ?
( ISNULL([TRX_MORG]) or TRIM([TRX_MORG]) == "" ?
NULL(DT_WSTR,50)
: [TRX_MORG]
)
: [CASE_MORG]
)
: (ISNULL([CASE_AGT]) or TRIM([CASE_AGT]) == "" ?
( ISNULL([TRX_AGT]) or TRIM([TRX_AGT]) == "" ?
NULL(DT_WSTR,50)
: [TRX_AGT]
)
: [CASE_AGT]
)

I don't think there is any limit with nesting conditions. Even if there is one, I don't think we will reach the limit in the packages that we create handle our business processes.
You almost got everything correct. The issue with your conditional statement is that you have used or instead of ||
I copied your exact statement and pasted in Derived Transformation within a Data Flow task and got an error because the package couldn't parse the expression. I replaced all the or's with correct Logical OR (||) operator and the expression evaluated correctly.

Related

SSIS Derived Column Expression - removing leading zeros

I have a package that is failing due to a negative sign with a numerical string such as:
000000000-25.00
The Derived column expression is:
ISNULL(wstr_Payment_Amount) || TRIM(wstr_Payment_Amount) == "" ? (DT_CY)0 : (DT_CY)wstr_Payment_Amount
The data type to column is money. I did a redirect row on the derived column to confirm it was the negative sign that was causing the failure.
Here is what I have..
FINDSTRING(wstr_Payment_Amount, "-", 1) >0 ? TRIM(SUBSTRING(wstr_Payment_Amount, FINDSTRING(wstr_Payment_Amount, "0-", 1), 8)) : wstr_Payment_Amount
I am using SSIS 2008.
If you are using two derived columns then leave it as a string in the first one...
ISNULL(wstr_Payment_Amount) || TRIM(wstr_Payment_Amount) == "" ? (DT_WSTR,100)"0" : (DT_WSTR,100)wstr_Payment_Amount
I think you were really close but consider the following once you identify the negative sign...
FINDSTRING(wstr_Payment_Amount, "-", 1) >0 ? (DT_CY) ("-" + replace(wstr_Payment_Amount,"-","")) : (DT_CY)wstr_Payment_Amount
This will just move the "-" to the front and all the zeroes will just go away.

OR operator in JSONPath?

Using a single JSONPath expression alone, is it possible to do some kind of 'OR' or '||' operator. For example, these two JSONPath boolean expressions work to check the severity of a log JSON file:
$..log[?(#.severity == 'WARN')]
$..log[?(#.severity == 'Error')]
But I'd like to do something logically similar to:
$..log[?(#.severity == 'WARN' or #.severity == 'Error')] //this is not correct
Is there any way to do this?
If you are using Goessner's parser, you can use the || operator within your expression as follows:
$..log[?(#.severity == 'WARN' || #.severity == 'Error')]
From the JSONPath page:
[,] - Union operator in XPath results in a combination of node sets. JSONPath allows alternate names or array indices as a set.
Try
$..log[?(#.severity == 'WARN'), ?(#.severity == 'Error')]
Edit: Looks like there is an open issue for logical AND and OR operators in which they state that the operators are not yet supported by JSONPath.
Thank you for your answers. In my use case I got it working by combining the two answers from #sirugh and #elyas-bhy.
$..log[?(#.severity == 'WARN') || ?(#.severity == 'Error')]

SSIS expression fails to validate

I have set a following expression in SSIS derived column component:
TRIM(xCOL) == "" ? (DT_STR,7,1252)xCOL : NULL(DT_STR,7,1252)
However, this fails to validate - I get the following error:
Error at PKG: For operands of the conditional operator, the data type
DT_STR is supported only for input columns and cast operations. The
expression "TRIM(xCOL) == "" ? (DT_STR,7,1252)xCOL :
NULL(DT_STR,7,1252)" has a DT_STR operand that is not an input column
or the result of a cast, and cannot be used with the conditional
operation. To perform this operation, the operand needs to be
explicitly cast with a cast operator.
What is wrong here?
Unicode - the bane of all SSIS things that you would think just work.
TRIM(xCOL) == "" ? (DT_STR,7,1252)xCOL : NULL(DT_WSTR, 7)
By default, expressions on strings have a return type of Unicode (DT_WSTR). You can prove this yourself by replacing your last expression with an empty string "". Look at at the type that the derived column is assigned as - it's a DT_WSTR
TRIM(xCOL) == "" ? (DT_STR,7,1252)xCOL : ""
The resolution then is to cast the result of the entire expression to your desired type. (I also think you have a logic issue since I'm assuming you are inspecting the trimmed string to determine if it's empty/zero length and then casting it to NULL). Also note, that if you ever do get a NULL in for your xCOL field, this will blow up.
(DT_STR, 7, 1252)((TRIM(xCOL) == "") ? NULL(DT_WSTR, 7) : TRIM(xCOL))
Source data
SELECT 'Hello' AS xCOL
UNION ALL SELECT ''
Results
Like the error says, you must explicitly cast with a cast operator.
TRIM(xCOL) == "" ? (DT_STR,7,1252)xCOL : (DT_STR,7,1252)NULL(DT_STR,7,1252)

SSIS Equality Operator not working as expected

I have an SSIS package that is hooked into a MySQL database that has a tinyint(1) field which is set to the value 4 and I'm checking to see if that value is 4 in the database because it should not change based on the incoming flat file if it is already set to 4, but it doesn't seem to be working.
It should not be updating the status because the field is set to 4 but I guess I just don't understand why the expression isn't working. I have tried all the different int types for SSIS and it doesn't matter because it always sets the status to 1. Based on a quick google search a tinyint should be an unsigned 1 byte int which is why I am casting it to DT_UI1
Incoming values from flat file the first being the product and the last being the status
"039414","*****","*****","*****","*****","*****","*****","*****"," "
Existing value from the database the first being the product and the second being the status
039414 4
I handle the status by the following derived column expression, basically if there is no value it should be 1 otherwise it should be 4
LEN(TRIM(Status)) > 0 ? (DT_UI1)4 : (DT_UI1)1
Here is the derived column expression that I'm using to set the product_status (products_status being the actual field from the database and prod_status the status from the incoming flat file):
((DT_UI1)products_status == (DT_UI1)4) || ISNULL(prod_status) ? (DT_UI1)4 : (DT_UI1)prod_status
What I'm expecting to happen is a few products should keep their status of 4 but are being updated to 1, does anyone have an idea why?
Edit:
I tried changing the expression to the following with no success.
(DT_UI1)products_status == (DT_UI1)4 || ISNULL(prod_status) ? (DT_UI1)4 : (DT_UI1)prod_status
and
((DT_UI1)products_status == (DT_UI1)4 || ISNULL(prod_status)) ? (DT_UI1)4 : (DT_UI1)prod_status
and just the base test
(DT_UI1)products_status == (DT_UI1)4 ? (DT_UI1)4 : (DT_UI1)prod_status
Solution:
I ended up casting the field in the query to an integer because it was being pulled in as a boolean instead of an int
CAST(products_status AS SIGNED)
Then changed my expression to the following and it worked as expected
(products_status == 4 || ISNULL(prod_status)) ? (DT_I4)4 : prod_status
Not sure about the precedence here, but don't you think you want extra parentheses around the condition in the immediate if:
( ((DT_UI1)products_status == (DT_UI1)4) || ISNULL(prod_status) ) ? (DT_UI1)4 : (DT_UI1)prod_status
Looks like it might otherwise return "true", which is sometimes rendered as 1.
UPDATE
Here is a link to Data Viewer which lets you see what values SSIS is assigning to the columns and helps you analyze situations like this.
Your original expression
((DT_UI1)products_status == (DT_UI1)4) || ISNULL(prod_status) ? (DT_UI1)4 : (DT_UI1)prod_status
returns a boolean. Let's assume products_status is 4 and prod_status is also set to 4.
((DT_UI1)products_status == (DT_UI1)4)
Evaluates as TRUE.
ISNULL(prod_status) ? (DT_UI1)4 : (DT_UI1)prod_status
Evaluates as 4.
Your original expression now evaluates as
TRUE || 4
Which evaluates to
TRUE
Which when you try to stick it in an integer column like products_status becomes 1.
Your first revision makes no substantive change to the evaluation chain and also returns TRUE (i.e. 1).
Your second revision is the correct formulation of the ternary operator, as is the final base test. However, it appears that ISNULL(prod_status) always returns FALSE in your case since you are explicitly setting it to 4 or 1 in your other derived column, so let's ignore your second revision and just go to your final base test.
With regards to your final base test, I would definitely:
Attach a Data Viewer before your Derived Column component to ensure that the products_status column being passed in is indeed set to 4
Set a Data Viewer after your Derived Column component to see that products_status has been set (or not set) properly;
Make sure that you properly mapped the products_status field to your database destination and not the prod_status field by mistake.

LINQ subquery IN

I'm a newbie with the IQueryable, lambda expressions, and LINQ in general. I would like to put a subquery in a where clause like this :
Sample code :
SELECT * FROM CLIENT c WHERE c.ETAT IN (
SELECT DDV_COLUMN_VAL FROM DATA_DICT_VAL
WHERE TBI_TABLE_NAME = 'CLIENT' AND DD_COLUMN_NAME = 'STATUS'
AND DDV_COLUMN_VAL_LANG_DSC_1 LIKE ('ac%'))
How do I translate this in LINQ ?
var innerquery = from x in context.DataDictVal
where x.TbiTableName == myTableNameVariable
&& x.DdColumnName == "Status"
&& x.DdbColumnValLangDsc1.StartsWith("ac")
select x.DdvColumnVal;
var query = from c in context.Client
where innerquery.Contains(c.Etat)
select c;
from c in db.Client
where (from d in db.DataDictVal
where d.TblTableName == "Client"
&& d.DDColumnName == "Status"
&& dd.DdvColumnValLandDsc1.StartsWith("ac"))
.Contains(c.Etat)
select c;
If you are new to Linq, you absolutely need two essential tools. The first is a tool that converts most T-SQL statements to Linq called Linqer (http://www.sqltolinq.com/). This should take care of the query in your question. The other tool is LinqPad (http://www.linqpad.net/). This will help you learn Linq as you practice with queries.
I often use Linqer to convert a T-SQL query for me, and then use LinqPad to fine tune it.
Same example with Linq method syntax:
var innerquery = dbcontext.DataDictVal
.where(x=> x.TbiTableName == myTableNameVariable
&& x.DdColumnName == "Status"
&& x.DdbColumnValLangDsc1.StartsWith("ac"))
.select(x=>x.DdvColumnVal)
var query = dbcontext.Client
.where( c=>innerquery.Contains(c.Etat))
Note:
Am providing this answer, because when i searched for the answer, i couldn’t find much answer which explains same concept in the method syntax.
So In future, It may be useful for the people, those who intestinally searched method syntax like me today.
Thanks
karthik