SSIS: Precedence Constraint not working as expected - sql-server

Referring to the below snapshot, I am trying to use "Logical AND All constraint must be evaluated to true". In Expression, I am trying to equate Variable value with the current date and when checking it on evaluation expression it shows true when the condition is matching but still while running the package it doesn't move to the next step.
Expression used:
#[User::LastUpdated] == (DT_DBDATE) GETDATE()
Please help on this issue. Thanks.

The second screenshot shows that the Script Task is executed successfully which means that the first constraint is met. You should make sure that the #[User::LastUpdated] date value is equal to (DT_DBDATE)GETDATE().
Hint: Make sure that the #[User::LastUpdated] date value does not include the time part. You can use the following expression to avoid the time part problem:
(DT_DBDATE)#[User::LastUpdated] == (DT_DBDATE)GETDATE()

Related

SQL Server Report expression failing for NULL int values

IIF is giving me some hell. When I do this everything works:
=IIF (IsNothing(First(Fields!Temperature.Value, "ReportInfoDataSet")),"NULL","GOOD")
But when I want to actually use the value, I end up with #Error for the NULL values, and from what I've read it's because IIF evaluates everything at once, so the .ToString() argument fails for the "GOOD" condition even though it is not used.
This gives #Error when I have a null value:
=IIF(
IsNothing(First(Fields!Temperature.Value, "ReportInfoDataSet")),
"N/A",
First(Fields!Temperature.Value, "ReportInfoDataSet").ToString()
)
So how do I work around the fact that IIF wants to evaluate all terms? There is a TechNet article that shows nesting another IIF statement as the "GOOD" condition that helps with the NULL value, but I still get the error (doing this for example):
=IIF(
IsNothing(First(Fields!Temperature.Value, "ReportInfoDataSet")),
"N/A",
IIF(
IsNothing(First(Fields!Temperature.Value, "ReportInfoDataSet")),
"N/A",
First(Fields!Temperature.Value,"ReportInfoDataSet").ToString() & ChrW("&H00B0") & "F"
)
)
Here is the article that indicates this potential solution, but it seems that I am still missing something, or that something changed invalidating this solution.
One further bit of information: I put a breakpoint in just after I fill the datatable, thinking that I would just intercept the table fill and modify so that NULLs turn to 0 or something, and it seems that datatables are strongly typed and don't allow for nullable data types so there is an exception for the temperature column:
'(ReportInfoRow((new System.Linq.SystemCore_EnumerableDebugView((test.Table).Rows)).Items[0]))
.Temperature' threw an exception of type 'System.Data.StrongTypingException'
Any insights are valued . . . I'm pondering whether I just want to add an extension to the dataset and add a MyTemp parameter that fixes the value for the report.
To not have the .ToString() forced in the lack of short-circuit Boolean evaluation above, replace it with CSTR().
CSTR(First(Fields!Temperature.Value, "ReportInfoDataSet"))

How does the operator >+ differ from >= in SQL Server 2012

Entirely by accident today I was running a SQL statement to filter some items by date, for simplicity sake we'll say I used
SELECT *
FROM [TableName]
WHERE [RecordCreated] >+ '2016-04-10'
Only after the statement ran I realised I had used >+ instead of >=, now I was confused as I would have expected an error.
I tried a couple of other variations such as
>- -- Throws an error
<+ -- Ran successfully
<- -- Throws an error
The count of rows returned was exactly the same whether I used >= or >+
After searching online I couldn't find any documentation that covered this syntax directly, only when the two operators are used apart.
The RecordCreated column is a datetime.
Is this just a nicety in syntax for a possible common mistake or is it potentially trying to cast the date as a numeric value?
This seems to be a bug with '+' operator.
As per the updates from Microsoft team,
After some investigation, this behavior is by design since + is an
unary operator. So the parser accepts "+ , and the '+' is
simply ignored in this case. Changing this behavior has lot of
backward compatibility implications so we don't intend to change it &
the fix will introduce unnecessary changes for application code.
You can find a really good answer by RGO to his own question here.
The result shouldn't match with ">=" and "<=" but with ">" and "<". Just checked and the rowcound varies by 2 - the first and last item is removed.

How are SSIS Precedence Constraints Evaluated?

Maybe this question seems very basic and elementary but I need some clarification.
In SSIS the following Constraints are available to control component execution flow:
Logical AND. All constraints must evaluate to true.
Logical OR. At least one constraint must evaluate to true.
I have a very simple package I am using to test the conditions described.
A Process Task - calls a batch file that returns a string value and exit code.
The Process Task receives the value from the batch file as a StandardOutputVariable and assigns it to my user defined variable User::BatchExecutionCode
A Script Task - for validation, displays the acquired value from my user variable so I can visually see and affirm that the expected value is getting passed
An Execute SQL Task - That simply does a SELECT GETDATE().
I have setup a Logical AND condition between the Script Task and Process Task that mandates:
Constraint - Task execution must "Complete"
Expression - #BatchExecutionCode == "0"
When I execute, both tasks prior to the final "Execute SQL" task complete and I get a visual message box showing the value of my variable as "0" but the execution just stops afterward and never executes the last task after evaluation.
What is the problem? According to the stated conditions for execution, the conditions have been met. So exactly how are the precedence constraints being evaluated.
EDIT: For clarification, In the screenshot the value of #BatchExecutionCode has been passed to User::Result variable via the Script Task. Thats why the Expression says #Result == "0". Either way, the results is still the same
The only reason should be #Result doesn't equal "0", you can confirm that with a post execute breakpoint on you script task.
You can use the following article to confirm what's really in this variable.
http://www.jasonstrate.com/2011/01/31-days-of-ssis-using-breakpoints-231/

Set local variable in rdlc expression

Is it possible to somehow create variable in rdlc report expression in 'online' manner?
For example, I have following expression:
=IIf(First(Fields!BillingAccount_billtostateprovince.Value, "Invoice") <> "",
First(Fields!BillingAccount_billtostateprovince.Value, "Invoice") + " ",
"")
I suppose that I'm evaluating following expression First(Fields!BillingAccount_billtostateprovince.Value, "Invoice") twice. I don't like it and it looks ugly... I would prefer to create variable in the scope of current expression and use it.
Is it possible?
As user3056839 said, Welcome to SSRS!
Anyway, what you want is not possible since what you are writing right now is not a script but it's just an expression. It's a single statement that returns a value, so you cannot declare variables, use loops or anything that is part of a script.
You have to use exactly what you are writing.
Also it's not rare to see an IIF expression like yours. The one I constantly see is IFF( IS NOT NULL, , 'N/A'). The field may actually be evaluated twice, but there's nothing you can do. It's ugly but it's the only way you can do that.
Just think about the CASE WHEN clause:
SELECT
CASE WHEN MyField IS NOT NULL THEN
MyField ELSE 0
END
You are evaluating the field twice, but there's nothing you can do :)
It is possible to do it in SQL Server 2008 and above. You can create a Report Variable which can be accessed through out your report.
Reference: sqlchick.com

SSIS: execute first task if condition met else skip to next

I am getting to know SSIS, I apologize if the question is too simple.
I got a set of tasks inside a foreach-loop-container.
The first task needs only to get executed on condition that a certain user variable is not null or empty.
Otherwise, the flow should skip the first task and continue to the second one.
How would I go about realizing this (in detail) ?
Issue 1: There are two ways to interpret your logic: "...a certain user variable is not null or empty":
The (Variable is Not Null) OR the (Variable is Empty).
The (Variable is Not Null) OR the (Variable is Not Empty).
It's all about the object(s?) of the word "not". The differences are subtle but will impact when the first task in the Foreach loop executes. For demonstration purposes, I am assuming you intend #1.
Issue 2: The first task can no longer be first. In order to accomplish what you desire using SSIS inside the BIDS environment, you need to place another task ahead of the task formerly known as "the first task". This is so you can set a Precedence Constraint on the former first task from the new first task.
It is possible to accomplish what you desire by designing your SSIS dynamically from managed code, but I don't think this issue warrants the overhead associated with that design choice.
I like using an empty Sequence Container as an "Anchor" task - a task that exists solely to serve as the starting endpoint of a Precedence Constraint. I heavily document them as such. I don't want anyone deleting the "unnecessary empty container" and roaming the halls for days shaking their heads and repeating "Andy, Andy, Andy..." but I digress.
In the example below, I have two precedence constraints leaving the empty Sequence Container. One goes to the task that may be skipped and the other to the task following the task that can sometimes be skipped. A third precedence constraint is required between the task that can sometimes be skipped and the task following. It is important to note this third precedence constraint must be edited and the Multiple Constraints option set to OR. This allows the task following to execute when either of the mutually exclusive previous paths are taken. By default, this is set to AND and will require both paths to execute. By definition, that will not - cannot - happen with mutually exclusive paths.
I test the value of an SSIS String variable named #MyVar to see if it's Null or Empty. I used the Expression Only Evaluation Option for the constraints leaving the empty Sequence Container. The expressions vary but establish the mutual exclusivity of the expression. My Foreach Loop Container looks like this:
I hope this helps.
:{>
The best thing can be to use the 'Disable Property' in expressions and giving the expression as per the condition. Just search how to use the disable property.
How about a simple solution instead of some of the more complex ones that have already been given. For the task you want to conditionally skip, add an expression to the disabled property. Any expression that produces a true or false result will work, so for the question example you could use:
ISNULL(#[User::MY_VAR]) || #[User::MY_VAR]==""
The only downside is that it may not as visible as some of the other solutions but it is far easier to implement.
I would create a For Loop Container around the task that needs the condition with the following conditions (#iis the loop counter, #foo is your user variable that you want to test):
InitExpression: #i=0
EvalExpression: #i<1 && !ISNULL(#Foo) && #Foo!=""
AssignExpression: #i=#i+1
there is no need to create a "script"
I think the best (and simpler) approach is to add a blank script task inside your loop container before your "first task", drag the green arrow from it to your "first task" (which obviously will become the second) and use the precedence constraint to do the check.
To do that, double click the arrow, select "expression" on the "evaluation operation" and write your expression. After hitting OK the arrow will become blue indicating that it isnt a simple precedence constraint, it has a expression assigned to it.
Hopefully I didn't misunderstand the question but a possible solution can be as written below.
I created a sample ForEach loop. The loop itself is an item enumerator. It enumerates the numbers 1, 2, 3. The acutal value is stored in a variable called LoopVariable.
There is another variable named FirstShouldRun which is a Boolean variable showing the first task in the foreach loop should be runned or not. I set this variable's EvaluateAsExpression property to true, and its expression is (#[User::LoopVariable] % 2) == 0. I would like to demonstrate with this that every second time the first task should be started.
The two tasks do nothing much but display a MessageBox showing the task has been started.
I started the package and first and the third time the first task didn't started. In the second loop the MessageBox (showing "First started") appeared.
After that you should set FirstShouldRun variable as you like.
As I mentioned in my first comment to the OP, this solution is based on the idea of Amos Wood written in another answer.
That's a bit tricky.
You have to create a Script Task and check if your variable is not null in there.
So first you have the script task in which you will have the following code in your Main() function:
public void Main()
{
if (Dts.Variables["User::yourVariable"].Value != null)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
else
{
Dts.TaskResult = (int)ScriptResults.Success;
}
}
Then you create two connections from your script task, one to the task that needs to be executed when your variable is not null, and one to the next task (or to another script, if you need to check again, if the variable is not null).
Then you right-click on the (green) arrow of your first connection and select "Failure". Right-click the connection to the next task / script and set it to "Completion".
It should then look something like this:
That's it.

Resources