I have the following tasks in SSIS:
In Check Stock task, I execute a stored procedure which returns 0 or 1:
CREATE PROCEDURE [dbo].[SP_CheckStockAvailability]
AS
BEGIN
DECLARE #ItemGID nvarchar(250)=(SELECT TOP (1) ItemGID FROM XMLOrderlines WHERE Comparison='0')
SELECT CASE
WHEN #ItemGID IS NOT NULL
THEN CAST (0 AS bit)
ELSE CAST (1 AS bit)
END AS Comparison
FROM XMLOrderlines
END
GO
I would like to execute Reject Order (on the right) task if the result is 1 and, if not, to execute the one from the left. I set to export the result of the procedure in a variable, Boolean data type with a default value of "False".
If I edit the precedence constraint and I set Expression as evaluation operation and then choose the variable from the previous task, either way it does not go to the next task that is supposed to. What am I missing? I tried what I found on the web but nothing helped me. Thanks!
Solution
You have to set the following values:
Reject Order
Evaluation operation: Expression and Constraint
Value: Success
Expression: #[User::Result] = 1
OR
#[User::Result]
Accept Order
Evaluation operation: Expression and Constraint
Value: Success
Expression: #[User::Result] = 0
OR
!#[User::Result]
Screenshot
Suggestions
I think it is better to add a TRY...CATCH block to your procedure, so if it encounters an error the result will be 1 and the Order is rejected:
CREATE PROCEDURE [dbo].[SP_CheckStockAvailability]
AS
BEGIN
BEGIN TRY
DECLARE #ItemGID nvarchar(250)=(SELECT TOP (1) ItemGID FROM XMLOrderlines WHERE Comparison='0')
SELECT CASE
WHEN #ItemGID IS NOT NULL
THEN CAST (0 AS bit)
ELSE CAST (1 AS bit)
END AS Comparison
FROM XMLOrderlines
END TRY
BEGIN CATCH
SELECT 1 AS Comparison
END CATCH
END
GO
Try choosing Evaluation Operation to Expression and Constraint and the expression has to be smth like #[User::Result] = 1. The expression has to return True or False.
For more informations, follow this link:
Working with Precedence Constraints in SQL Server Integration Services
The expression for 1/True should be #[User::Result], as you have, and the expression for 0/False should be !#[User::Result] (notice the exclamation mark).
You may also want to look into using "Expression and Constraint" as an "Evaluation operation", as without that, the flow will continue regardless of whether "Check stock" succeeds or fails (unless that is the desired behaviour). The "Constraint" part of this is what the "Value" field represents - in your image it is set to Failure, but greyed out (due to having only "Expression" selected) and therefore inactive.
Related
I'm getting the error
The data type for parameter or SQL variable "SHAPE" is not supported in the routine, compound SQL statement, or parameter list of a cursor value constructor.. SQLCODE=-789, SQLSTATE=429BB, DRIVER=4.18.60
When I use the code
CREATE OR REPLACE TRIGGER z
BEFORE INSERT OR UPDATE ON x
REFERENCING NEW AS N
FOR EACH ROW
BEGIN
DECLARE contador INTEGER;
SET contador = (SELECT COUNT(*) FROM y s
WHERE NOT(n.yID = s.yID AND db2gse.ST_Contains(s.shape, n.shape) = 1));
IF contador > 0 THEN
SIGNAL SQLSTATE '20001' SET MESSAGE_TEXT ='invalid relationship';
END IF;
END#
But if take out the function ST_Contains, it's works, I don't have a clue why that happens.
EDIT: Windows 7 64bit Ultimate with DB2 11.1 Server edition with ibm data studio, sorry I forgot about this detail.
Well, the error message does give you a clue: structured types (which ST_Geometry and its children are) are not supported in compound SQL statements, such as your trigger body. You'll need to do this check before you convert data from the exchange format to geometry or store the exchange format in the table along with geometry.
In the latter case you would have, along with the shape ST_Geometry column another one, e.g. shape_wkt varchar(5000) and in the trigger do type conversion on the fly:
...AND db2gse.ST_Contains(
db2gse.ST_Geometry(s.shape_wkt),
db2gse.ST_Geometry(n.shape_wkt)
)
db2gse.ST_Geometry(s.shape_wkt) might be optional, because the value does not need to be instantiated in the trigger, so this might work:
...AND db2gse.ST_Contains(
s.shape,
db2gse.ST_Geometry(n.shape_wkt)
)
In the book "T-SQL Fundamentals", for the "UPDATE" with "assignment" query below, the author stated:
The specialized UPDATE syntax is run as a transaction, and it’s more
efficient than using separate UPDATE and SELECT statements because it
accesses the data only once. Note that variable assignment isn’t
transactional, though.
CREATE TABLE dbo.MySequences
(
id VARCHAR(10) NOT NULL CONSTRAINT PK_MySequences PRIMARY KEY(id),
val INT NOT NULL
);
INSERT INTO dbo.MySequences VALUES('SEQ1', 0);
DECLARE #nextval AS INT;
UPDATE dbo.MySequences
SET #nextval = val += 1
WHERE id = 'SEQ1';
SELECT #nextval AS nextValue;
I'm a little bit confused as to why "UPDATE" statement is run as a transaction, but the variable assignment (i.e. SET #nextval = val += 1) isn't transactional? Isn't the variable assignment part of the "UPDATE" statement?
Could someone please clarify the concept?
It cannot be transactional because it's recursive update. But each recursive run is under implicit transaction.
It means update first row by my variable, and add to my variable old value +1, then second run update second row, add to my variable old value +1...
If you would like atomic solution use rownumber or sequency.If you would like to use transaction use explicit transaction.
I am writing a postgresql function but I cannot seem to find where the error is. Postgresql is at version 9.4.
The following is the function:
CREATE FUNCTION custom_function1()
RETURNS trigger
LANGUAGE plpgsql
AS
$$
DECLARE base_val integer;
BEGIN
base_val := (EXTRACT(YEAR FROM now())::integer * 10000000000);
IF (currval('custom_sequence') < base_val) THEN
setval('custom_sequence', base_val);
END IF;
NEW.id := custom_function2();
RETURN NEW;
END;
$$;
My custom_sequence is in the format YYYY0000000000 (ex. 20150000000000).
So what this basically does (should do) is it checks if the base_val (minimum value for current year) is greater then the currval (current custom_sequence value) and updates the custom_sequence value. Then it returns a new value for that sequence generated with the function custom_function2 (which formats it slighly).
When I try to execute this it gives me:
syntax error at or near "setval"
I am pretty new to both postgresql and writing functions so I am probably not seeying an obvious error. If someone could help me it would be highly appreciated, thank you.
The error is related to what's explained in the doc here:
40.5.2 Executing a Command With No Result
[...]
Sometimes it is useful to evaluate an expression or SELECT query but
discard the result, for example when calling a function that has
side-effects but no useful result value. To do this in PL/pgSQL, use
the PERFORM statement:
PERFORM query;
You should write:
PERFORM setval('custom_sequence', base_val);
Hi i have the following stored procedure...
CREATE OR REPLACE PROCEDURE DB.INSERTGOOD
(
--CapRefCursor OUT Cap_Cur_Pkg.CapCur,
p_APPLIANT_TLT IN GOODRIGHT_MANUAL.APPLICANT_TLT%TYPE,
p_APPLIANT_NME IN GOODRIGHT_MANUAL.APPLICANT_NME%TYPE,
p_APPLICANT_SURNME IN GOODRIGHT_MANUAL.APPLICANT_SURNME%TYPE,
p_COMPANY_NME IN GOODRIGHT_MANUAL.COMPANY_NME%TYPE,
p_ID_CDE IN GOODRIGHT_MANUAL.ID_CDE%TYPE,
p_ADD1 IN GOODRIGHT_MANUAL.ADD1%TYPE,
p_OCCUPATION1 IN GOODRIGHT_MANUAL.OCCUPATION1%TYPE,
p_REMARK1 IN GOODRIGHT_MANUAL.REMARK1%TYPE,
p_SOURCE IN GOODRIGHT_MANUAL.SOURCE%TYPE
)
IS
BEGIN
INSERT
INTO GOODRIGHT_MANUAL
(
SEQ_ID,
APPLICANT_TLT,
APPLICANT_NME,
APPLICANT_SURNME,
COMPANY_NME,
ID_CDE,
ADD1,
OCCUPATION1,
REMARK1,
GOODRIGHT_MANUAL.SOURCE
)
VALUES
(
goodright_seq.nextval,
p_APPLIANT_TLT,
p_APPLIANT_NME,
p_APPLICANT_SURNME,
p_COMPANY_NME,
lower(p_ID_CDE),
p_ADD1,
p_OCCUPATION1,
p_REMARK1,
p_SOURCE
);
COMMIT;
-- OPEN CapRefCursor FOR
--select 'True';
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN ROLLBACK;
-- select 'False';
END DB.INSERTGOOD;
/
Here i want to return a string TRUE if the transaction commit successfully and FALSE if transaction rollback.
An Output Variable CapRefCursor is defined but i don't know how to assign true false to that variable and return it.
Thanks in advance.
You have defined a procedure with no OUT parameter, therefore it can not return anything.
You have several options to return success information:
define a function instead of a procedure. A function always returns something, you can define a string to be returned as VARCHAR2 for example in your case.
add an OUT parameter to the procedure. OUT parameters are logically equivalent to function returned values. You can have more than one such parameters.
modify your logic so that the procedure returns nothing when it works and throws an exception when it fails.
I would go with solution (3) because:
solution (1) and (2) are bug-prone: you may easily forget to check the return code in which case your program will continue as if no error had happened in case of failure. Ignoring error is the surest way to transform a benign bug into a monstrosity because it can lead to extensive data corruption. Your program may go on for months without you realising that it is intermittently failing!
Exception logic is designed to overcome this problem and makes the code cleaner and clearer. No more ugly if-then-else after every single procedure call. For this reason alone, solutions (1) and (2) are considered code-smell (anti-pattern) when used extensively to return success/error state.
Less code is involved, just remove the EXCEPTION block and let the error propagate.
procedures that fail will undo their work without rolling back the whole transaction if you let the exception propagate (and don't issue intermediate commits).
Finally, in general you should not control transaction logic in your sub-procedures. A procedure that does a single insert is probably part of a larger transaction. You should not let this procedure either commit or rollback. Your calling code, be it PL/SQL, GUI or script should decide if the transaction should move forward and complete or be rolled back.
I don't get the simple boolean algebra on my sql-server. According to msdn, the following statement should return "1", but on my server it returns "0".
Can you help me?
SET ANSI_NULLS ON
SELECT CASE WHEN NOT(1=NULL) THEN 1 ELSE 0 END
Please have a look at msdn. There it clearly states: "Comparing NULL to a non-NULL value always results in FALSE." - no matter what the ANSI_NULLS-setting is. Thus "1=NULL" should be FALSE and NOT(FALSE) should thus be TRUE and the statement should return "1".
But on my machine, it returns "0"!
One explanation might be, that "1=NULL" evaluates to "UNKNOWN". NOT(UNKNOWN) is still UNKNOWN (msdn), which would force the CASE-Statement into the ELSE.
But then the official documentation of the equals-operator would be wrong. I cannot believe this!
Can anybody explain this behaviour?
Thank you very much for any help!
Edit (2012-03-15):
One thing I just found that might be of interest for some of you:
CREATE TABLE #FooTest (Value INT)
ALTER TABLE #FooTest WITH CHECK ADD CONSTRAINT ccFooTestValue CHECK (Value>1)
PRINT '(NULL>1) = ' + CASE WHEN NULL>1 THEN 'True' ELSE 'False' END
INSERT INTO #FooTest (Value) VALUES (NULL)
The print-Statement writes 'False', but the insertion runs without error.
SQL-Server seems to negate the check-constraint in order to search for rows that do not fulfill the constraint-check:
IF EXISTS (SELECT * FROM inserted WHERE NOT(Value>NULL)) <Generate error>
Since the check-constraint evaluates to UNKNOWN, the negation is also UNKNOWN and SqlServer does not find any row violating the check-constraint.
Yes that link is wrong. File a documentation bug on Microsoft Connect.
Sql uses three valued logic not boolean logic. true, false, and unknown
Most comparison operators (i.e. excluding IS [NOT] NULL) involving NULL result in unknown not True or False. Negating unknown yields unknown as per the truth tables shown here.
The MSDN page for Equals that you link to definitely appears incorrect.
Check the MSDN page for SET ANSI_NULLS.
When SET ANSI_NULLS is ON, all comparisons against a null value
evaluate to UNKNOWN.
To get that example SQL statement to work as expected, you should use compare using "IS NULL" or "IS NOT NULL" instead of using the equals operator (=). For example:
SELECT CASE WHEN NOT(1 IS NULL) THEN 1 ELSE 0 END
OR
SELECT CASE WHEN (1 IS NOT NULL) THEN 1 ELSE 0 END
You want to read the documentation on ANSI_NULLS. SQL actually implements a ternary logic, not boolean logic, where a comparison operation can result in true, false or undefined. Basically, this means that the explanation you proffered is correct.
This can be demonstrated with the following query:
SET ANSI_NULLS ON
SELECT CASE
WHEN (1=NULL) THEN 0
WHEN NOT(1=NULL) THEN 1
ELSE -1
END
Which results in -1 on my machine (SQL Server 2005 Enterprise). Changing the first line to SET ANSI_NULLS OFF produces 1 as expected.
So, is the official documentation wrong? I'd submit that is somewhat misleading. It says that it results in FALSE. Obviously this is wrong. What the documentation meant to say is that comparing a non-null to NULL always results in a mismatch whose value also depends on ANSI_NULLS.
Of course, on SQL Server 2012, the ANSI_NULLS setting has been removed, and therefore setting it any which way will not change the result.
It's not boolean logic, its trinary logic: {True, False, I Don't Know.} Break it down this way:
IF 1=NULL
print 'True'
else
print 'False'
Generates False because 1=NULL equals NULL, aka "not True"
IF not(1=NULL)
print 'True'
else
print 'False'
Also generates False because not(1=NULL) equals not(NULL) equals NULL, aka "not True". This gets you to
SELECT CASE WHEN NOT(1=NULL) THEN 1 ELSE 0 END
which as per above is the same as
SELECT CASE WHEN NULL THEN 1 ELSE 0 END
which, since NULL is not true, resovles to the ELSE clause.
In short, as far as I'm concerned the documentation is incorrect. Distressing, but not unique, and so not entirely surprising.
Try using EXISTS in a subquery, it uses 2 valued logic and will give you the true/false you are looking for.
From BOL (credit to Thomas):
SET ANSI_NULLS ON affects a comparison only if one of the operands of
the comparison is either a variable that is NULL or a literal NULL. If
both sides of the comparison are columns or compound expressions, the
setting does not affect the comparison.
So I guess the NOT operation is checking 1=NULL which is unknown and because this is not a variable or literal NULL gets the ELSE part of your comparison as you hypothesised.
1=NULL seems to return FALSE only when ANSI_NULLS is OFF. Otherwise it's indeterminate. The msdn page probably needs to be edited to clarify that point.
SET ANSI_NULLS OFF
SELECT CASE WHEN (1=NULL) THEN 'true' ELSE 'false or unknown' END --returns false or unknown
, CASE WHEN NOT(1=NULL) THEN 'true' ELSE 'false or unknown' END --returns true
go
SET ANSI_NULLS ON
SELECT CASE WHEN (1=NULL) THEN 'true' ELSE 'false or unknown' END --returns false or unknown
, CASE WHEN NOT(1=NULL) THEN 'true' ELSE 'false or unknown' END --returns false or unknown
go