I'm using Visual Studio 2019 and SQL Server SSIS.
In a precedence constraint, how do I use an AND within the expression?
For example if I have:
#myVariable1 == 0 AND #myVariable2 == 0
I get the message
Expression cannot be evaluated
This is what I am trying to achieve:
I know the double pipe operator is a logical OR, is there something similar for AND?
you need to use && like so
#myVariable1 == 0 && #myVariable2 == 0
here is complete list of SSIS expression operators:
Operator
Description
Cast
Converts an expression from one data type to a different data type.
() (Parentheses)
Identifies the evaluation order of expressions.
+ (Add) (SSIS)
Adds two numeric expressions.
+ (Concatenate)
Concatenates two expressions.
- (Subtract)
Subtracts the second numeric expression from the first one.
- (Negate)
Negates a numeric expression.
* (Multiply)
Multiplies two numeric expressions.
/ (Divide)
Divides the first numeric expression by the second one.
% (Modulo)
Provides the integer remainder after dividing the first numeric expression by the second one.
|| (Logical OR)
Performs a logical OR operation.
&& (Logical AND)
Performs a logical AND operation.
! (Logical NOT)
Negates a Boolean operand.
| (Bitwise Inclusive OR)
Performs a bitwise OR operation of two integer values.
^ (Bitwise Exclusive OR)
Performs a bitwise exclusive OR operation of two integer values.
& (Bitwise AND)
Performs a bitwise AND operation of two integer values.
~ (Bitwise NOT)
Performs a bitwise negation of an integer.
== (Equal)
Performs a comparison to determine if two expressions are equal.
!= (Unequal)
Performs a comparison to determine if two expressions are not equal.
> (Greater Than)
Performs a comparison to determine if the first expression is greater than the second one.
< (Less Than)
Performs a comparison to determine if the first expression is less than the second one.
>= (Greater Than or Equal To)
Performs a comparison to determine if the first expression is greater than or equal to the second one.
<= (Less Than or Equal To)
Performs a comparison to determine if the first expression is less than or equal to the second one.
? : (Conditional)
Returns one of two expressions based on the evaluation of a Boolean expression.
Related
If I let MySQL execute SELECT (0 < 1), it return 1; But if I run this select statement with SQL Server, it give me an error:
Incorrect syntax near '<'.
I also have tested other operator like != and <, and get the same error. I'm confused. '0 < 1' is an expression, why can't SQL Server evaluate it?
This behavior is by design:
Unlike other SQL Server data types, a Boolean data type cannot be
specified as the data type of a table column or variable, and cannot
be returned in a result set.
[...]
Expressions with Boolean data types are used in the WHERE clause to
filter the rows that qualify for the search conditions and in
control-of-flow language statements such as IF and WHILE
So Boolean datatype exists, you just cannot use it outside WHERE clause (etc).
The correct SQL Server equivalent of MySQL SELECT x < 1 (which returns 0, 1 or NULL) would be:
SELECT CASE
WHEN x < 1 THEN 1
WHEN NOT (x < 1) THEN 0
ELSE NULL -- you can omit this line
END
Finally, LEN(NULL) is NULL and (generally speaking) any operation on NULL yields NULL. So the condition IF LEN(NULL) < 1 will not execute, neither will IF LEN(NULL) >= 1.
MS SQL doesn't have a boolean type. It supports boolean expressions, but those cannot be values in variables or result sets.
The best you can do is something like
select case when 0 < 1 then 0 else 1 end
The result set will have a normal integer (the bit type is sometimes used to represent true/false values, but it's just a number with possible values of 1 and 0).
I'm confused. '0 < 1' is an expression, why can't SQL Server evaluate it?
It sort of is and sort of isn't. It's a predicate, and SQL Server treats predicates differently from other expressions which produce values.
SQL Server doesn't have a user-visible boolean data type so you cannot write an expression that produces a value of this non-existent data type.
You can only use predicates in specific positions, such as the WHERE clause, ON clauses, WHEN clauses (part of a CASE expression) and CHECK constraints (there are others)
Four simple SELECT statements:
SELECT 33883.50 * -1;
SELECT 33883.50 / -1.05;
SELECT 33883.50 * -1 / 1.05;
SELECT (33883.50 * -1) / 1.05;
But the results are not as I would expect:
-33883.50
-32270.000000
-32269.96773000
-32270.000000
That third result is the one that seems questionable. I can see what is happening, first SQL Server evaluates this:
SELECT -1 / 1.05;
Getting an answer of:
-0.952380
Then it takes that answer and uses it to perform this calculation:
SELECT 33883.50 * -0.952380;
To get the (wrong) answer of:
-32269.96773000
But why is it doing this?
In your example
33883.50 * -1 / 1.05
is evaluated as
33883.50 * (-1 / 1.05)
instead of
(33883.50 * -1) / 1.05
which results in a loss in precision.
I played a bit with it. I used SQL Sentry Plan Explorer to see the details of how SQL Server evaluates expressions. For example,
2 * 3 * -4 * 5 * 6
is evaluated as
((2)*(3)) * ( -((4)*(5))*(6))
I'd explain it like this. In T-SQL unary minus is made to be the same priority as subtraction, which is lower than multiplication. Yes,
When two operators in an expression have the same operator precedence
level, they are evaluated left to right based on their position in the
expression.
, but here we have an expression that mixes operators with different priorities and parser follows these priorities to the letter. Multiplication has to go first, so it evaluates 4 * 5 * 6 at first and then applies unary minus to the result.
Normally (say in C++) unary minus has higher priority (like bitwise NOT) and such expressions are parsed and evaluated as expected. They should have made unary minus/plus same highest priority as bitwise NOT in T-SQL, but they didn't and this is the result. So, it is not a bug, but a bad design decision. It is even documented, though quite obscurely.
When you refer to Oracle - that the same example works differently in Oracle than in SQL Server:
Oracle may have different rules for operator precedence than SQL Server. All it takes is to make unary minus highest priority as it should.
Oracle may have different rules for determining result precision and scale when evaluating expressions with decimal type.
Oracle may have different rules for rounding intermediate results. SQL Server "uses rounding when converting a number to a decimal or numeric value with a lower precision and scale".
Oracle may be using completely different types for these kind of expressions, not decimal. In SQL Server "a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary. For example, the constant 12.345 is converted into a numeric value with a precision of 5 and a scale of 3."
Even definition of decimal may be different in Oracle. Even in SQL Server "the default maximum precision of numeric and decimal data types is 38. In earlier versions of SQL Server, the default maximum is 28."
Do you know BODMAS rule. The answer is correct its not because of Sql Server, Its a basic mathematics.
First comes Division then comes the Subtraction, So always Division will happen before Subtraction
If you want to get correct answer then use proper parenthesis
SELECT (33883.50 * -1) / 1.05;
T-SQL has an rule for operator precedence which it follows. You can read about it on the link https://msdn.microsoft.com/en-us/library/ms190276.aspx.
It seems to be a precedence rule concerning unary operators. I have tried the following queries
SELECT 33883.50 * cast(-1 as int) / 1.05;
SELECT 33883.50 * (-1 * 1) / 1.05;
and it returns the right answer. The best thing to do is to use parentheses on expressions you want to occur first, and test thoroughly.
I have a rough understanding of why = null in SQL and is null are not the same, from questions like this one.
But then, why is
update table
set column = null
a valid SQL statement (at least in Oracle)?
From that answer, I know that null can be seen as somewhat "UNKNOWN" and therefore and sql-statement with where column = null "should" return all rows, because the value of column is no longer an an unknown value. I set it to null explicitly ;)
Where am I wrong/ do not understand?
So, if my question is maybe unclear:
Why is = null valid in the set clause, but not in the where clause of an SQL statement?
SQL doesn't have different graphical signs for assignment and equality operators like languages such as c or java have. In such languages, = is the assignment operator, while == is the equality operator. In SQL, = is used for both cases, and interpreted contextually.
In the where clause, = acts as the equality operator (similar to == in C). I.e., it checks if both operands are equal, and returns true if they are. As you mentioned, null is not a value - it's the lack of a value. Therefore, it cannot be equal to any other value.
In the set clause, = acts as the assignment operator (similar to = in C). I.e., it sets the left operand (a column name) with the value of the right operand. This is a perfectly legal statement - you are declaring that you do not know the value of a certain column.
They completely different operators, even if you write them the same way.
In a where clause, is a comparsion operator
In a set, is an assignment operator
The assigment operator allosw to "clear" the data in the column and set it to the "null value" .
In the set clause, you're assigning the value to an unknown, as defined by NULL. In the where clause, you're querying for an unknown. When you don't know what an unknown is, you can't expect any results for it.
as far as I know, in SQL,
X between Y and Z
gives the same result as
X >= Y and X <= Z
But I often see the latter from people I believe to be SQL experts.
Is there a subtle difference that I should know about?
Great question. In a nutshell, they are essentially the same. Documentation says:
expr BETWEEN min AND max
If expr is greater than or equal to min and expr is less than or equal to max, BETWEEN returns 1, otherwise it returns 0. This is equivalent to the expression (min <= expr AND expr <= max) if all the arguments are of the same type. Otherwise type conversion takes place according to the rules described in Section 12.2, “Type Conversion in Expression Evaluation”, but applied to all the three arguments.
reference: https://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_between
I believe the between syntax is not ANSI compliant, so it is not implemented in all databases. The most common one >= and <= can be used everywhere.
In Mathematics and many programming languages (and I think standard SQL as well), parentheses change precedence (grouping parts to be evaluated first) or to enhance readability (for human eyes).
Equivalent Examples:
SELECT array[1,2] #> array[1]
SELECT (array[1,2]) #> array[1]
SELECT array[1,2] #> (array[1])
SELECT ((array[1,2]) #> (array[1]))
But SELECT 1 = ANY array[1,2] is a syntax error (!), and SELECT 1 = ANY (array[1,2]) is valid. Why?
OK, because "the manual says so". But what the logic for humans to remember all exceptions?
Is there a guide about it?
I do not understand why (expression) is the same as expression in some cases, but not in other cases.
PS1: parentheses are also used as value-list delimiters, as in expression IN (value [, ...]). But an array is not a value-list, and there does not seem to be a general rule in PostgreSQL when (array expression) is not the same as array expression.
Also, I used array as example, but this problem/question is not only about arrays.
"Is there a summarized guide?", well... The answer is no, so: hands-on! This answer is a Wiki, let's write.
Summarized guide
Let,
F() a an usual function. (ex. ROUND)
L() a function-like operator (ex. ANY)
f a operator-like function (ex. current_date)
Op an operator
Op1, Op2 are distinct operators
A, B, C values or expressions
S a expression-list, as "(A,B,C)"
The rules, using these elements, are in the form
rule: notes.
"pure" mathematical expressions
When Op, Op1, Op2 are mathematical operators (ex. +, -. *), and F() is a mathematical function (ex. ROUND()).
Rules for scalar expressions and "pure array expressions":
A Op B = (A Op B): the parentheses is optional.
A Op1 B Op2 C: need to check precedence.
(A Op1 B) Op2 C: enforce "first (A Op1 B)".
A Op1 (B Op2 C): enforce "first (B Op2 C)".
F(A) = (F(A)) = F((A)) = (F((A))): the parentheses are optional.
S = (S): the external parentheses are optional.
f=(f): the parentheses are optional.
Expressions with function-like operators
Rules for operators as ALL, ANY, ROW, SOME, etc.
L(A) = L((A)): the parentheses is optional in the argument.
(L(A)): SYNTAX ERROR.
...More rules? Please help editing here.
ANY is a function-like construct. Like (almost) any other function in Postgres it requires parentheses around its parameters. Makes the syntax consistent and helps the parser avoid ambiguities.
You can think of ANY() like a shorthand for unnest() condensed to a single expression.
One might argue an additional set of parentheses around the set-variant of ANY. But that would be ambiguous, since a list of values in parentheses is interpreted as a single ROW type.