I have a column which is int and want to load the data based on condition for example say:
if the value is 1 then load column with inserted
value is 2 then load column with DELETED
value is 3 then load column with UPDATED
But when I tried doing this I am getting the following error:
Error at Data Flow Task [Derived Column [1666]]: Attempt to parse the expression "[Copy of operation]== "1" ? "INSERTED"" failed. The expression might contain an invalid token, an incomplete token, or an invalid element. It might not be well-formed, or might be missing part of a required element such as a parenthesis.
Error at Data Flow Task [Derived Column [1666]]: Cannot parse the expression "[Copy of operation]== "1" ? "INSERTED"". The expression was not valid, or there is an out-of-memory error.
Error at Data Flow Task [Derived Column [1666]]: The expression "[Copy of operation]== "1" ? "INSERTED"" on "Derived Column.Outputs[Derived Column Output].Columns[Derived Column 1]" is not valid.
Error at Data Flow Task [Derived Column [1666]]: Failed to set property "Expression" on "Derived Column.Outputs[Derived Column Output].Columns[Derived Column 1]".
(Microsoft Visual Studio)
===================================
Exception from HRESULT: 0xC0204006 (Microsoft.SqlServer.DTSPipelineWrap)
------------------------------
Program Location:
I assume the issue is that you have an incomplete expression. The ternary operator ? : has three parts to it (boolean expression) ? True bits : False bits
[Copy of operation]== "1" ? "INSERTED" : [Copy of operation]== "2" ? "DELETED" : [Copy of operation]== "3"? "UPDATED" : "UNKNOWN"
This expression would read
If the value of column copy of operation is 1, then return INSERTED
else If the value of column copy of operation is 2, then return DELETED
else If the value of column copy of operation is 3, then return UPDATED
else return UNKNOWN
This does assume the data type of the column Copy of operation is a string. If it's a whole number, then you'd remove the double quotes around the values 1,2,3.
In the comments, you've indicated the __$operation indicates the value of the operation as where 1 = delete, 2 = insert, 3 = update (before change), and 4 = update (after change)
Continue with the above pattern along with changing out the differences (1 is delete in comment whereas 1 is inserted in question) to generate values.
A different approach is to use a tiny lookup table. You could even define it with an inline query and use a Lookup Component to add your operation description into the data flow
SELECT
OperationId
, OperationName
FROM
(
VALUES ('1', 'INSERTED')
, ('2', 'DELETED')
-- etc
)D(OperationId, OperationName);
Again, ensure you have your data types aligned
Related
I have a stored procedure that I'm executing to create a drill-down report in SSRS. In my expression where this error is getting generated I have the following defined for a specific column value:
=IIF(ISNOTHING(Fields!RN) AND Fields!TermType = "New", Fields!WrittenPremium.Value, 0)
The Fields!WrittenPremium.Value is a MONEY datatype from SQL Server 2017 and the error shows the following:
The Value expression for the textrun "WrittenPremium.Paragraphs[0].TextRuns[0]' contains an error: [BC30311] Value of type 'Microsoft.ReportingServices.ReportProcessing.ReportObjectModel.Field' cannot be converted to 'String'.
I'm not sure why this conversion error is being generated and could use any help/direction. Thanks.
You need to specify the value property, not just the field. So a simple change to ....
=IIF(ISNOTHING(Fields!RN.Value) AND Fields!TermType.Value = "New", Fields!WrittenPremium.Value, 0)
... should work.
I have SSRS report parameter name "Status" which contains Passed and Failed values. In the report I have one column called Name. I want to hide this column when Status = "Failed" and I want to show this column when Status = "Passed" or Status = "Passed,Failed".
=IIF(InStr(JOIN(Parameters!Status.Value,","), "Failed"),True,False)
Above expression hide the Name column for when Status = "Passed,Failed".
You should be able to do this .. but with the join, you may not need the / ToString() bit
=IIF((JOIN(Parameters!Status.Value,",").ToString().Contains("Failed"),"True","False")
Alternative:
=IIf(InStr(JOIN(Parameters!Status.Value,",").ToString(),"Failed") > 0,"True","False")
How about this:
=String.Join(",", Parameters!Status.Label).Contains("Failed")
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.
I m trying to write if statement to give error message if user try to add existing ID number.When i try to enter existing id i get error .untill here it s ok but when i type another id no and fill the fields(name,adress etc) it doesnt go to database.
METHOD add_employee.
DATA: IT_EMP TYPE TABLE OF ZEMPLOYEE_20.
DATA:WA_EMP TYPE ZEMPLOYEE_20.
Data: l_count type i value '2'.
SELECT * FROM ZEMPLOYEE_20 INTO TABLE IT_EMP.
LOOP AT IT_EMP INTO WA_EMP.
IF wa_emp-EMPLOYEE_ID eq pa_id.
l_count = l_count * '0'.
else.
l_count = l_count * '1'.
endif.
endloop.
If l_count eq '2'.
WA_EMP-EMPLOYEE_ID = C_ID.
WA_EMP-EMPLOYEE_NAME = C_NAME.
WA_EMP-EMPLOYEE_ADDRESS = C_ADD.
WA_EMP-EMPLOYEE_SALARY = C_SAL.
WA_EMP-EMPLOYEE_TYPE = C_TYPE.
APPEND wa_emp TO it_emp.
INSERT ZEMPLOYEE_20 FROM TABLE it_emp.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'INFO'
TEXTLINE1 = 'Record Added Successfully.'.
elseif l_count eq '0'.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'INFO'
TEXTLINE1 = 'Selected ID already in database.Please type another ID no.'.
ENDIF.
ENDMETHOD.
I'm not sure I'm getting your explanation. Why are you trying to re-insert all the existing entries back into the table? You're just trying to insert C_ID etc if it doesn't exist yet? Why do you need all the existing entries for that?
If so, throw out that select and the loop completely, you don't need it. You have a few options...
Just read the table with your single entry
SELECT SINGLE * FROM ztable INTO wa WITH KEY ID = C_ID etc.
IF SY-SUBRC = 0.
"this entry exists. popup!
ENDIF.
Use a modify statement
This will overwrite duplicate entries with new data (so non key fields may change this way), it wont fail. No need for a popup.
MODIFY ztable FROM wa.
Catch the SQL exceptions instead of making it dump
If the update fails because of an exception, you can always catch it and deal with exceptional situations.
TRY .
INSERT ztable FROM wa.
CATCH sapsql_array_insert_duprec.
"do your popup, the update failed because of duplicate records
ENDTRY.
I think there's a bug when appending in internal table 'IT_EMP' and inserting in 'ZEMPLOYEE_20' table.
Suppose you append the first time and then you insert. But when you append the second time you will have 2 records in 'IT_EMP' that are going to be inserted in 'ZEMPLOYEE_20'. That is because you don't refresh or clear the internal table and there you will have a runtime error.
According to SAP documentation on 'Inserting Lines into Tables ':
Inserting Several Lines
To insert several lines into a database table, use the following:
INSERT FROM TABLE [ACCEPTING DUPLICATE KEYS] . This
writes all lines of the internal table to the database table in
one single operation. The same rules apply to the line type of
as to the work area described above. If the system is able to
insert all of the lines from the internal table, SY-SUBRC is set to 0.
If one or more lines cannot be inserted because the database already
contains a line with the same primary key, a runtime error occurs.
Maybe the right direction here is trying to insert the work area directly but before you must check if record already exists using the primary key.
Check the SAP documentation on this issue clicking the link before.
On the other hand, once l_count is zero because of l_count = l_count * '0'. that value will never change to any other number making that you won't append or insert again.
why are you retrieving all entries from zemployee_20 ?
You can directly check wether the 'id' exists already or not by using select single. If exists, then show message, if not, add.
It is recommended to retrieve only one field when its needed and not the entire table with asterisc *
SELECT single employee_id FROM ZEMPLOYEE_20 where employee_id = p_id INTO v_id. ( or field in structure )
if sy-subrc = 0. "exists
"show message
else. "not existing id
"populate structure and then add record to Z table
endif.
Furthermore, l_count is not only unnecessary but also bad implemented.
You can directly use the insert query,if the sy-subrc is unsuccessful raise the error message.
WA_EMP-EMPLOYEE_ID = C_ID.
WA_EMP-EMPLOYEE_NAME = C_NAME.
WA_EMP-EMPLOYEE_ADDRESS = C_ADD.
WA_EMP-EMPLOYEE_SALARY = C_SAL.
WA_EMP-EMPLOYEE_TYPE = C_TYPE.
INSERT ZEMPLOYEE_20 FROM WA_EMP.
If sy-subrc <> 0.
Raise the Exception.
Endif.
I am using a function I read about here to merge a series of recordsets that are generated by a stored procedure that is called in a loop. I have used this function before in other stored procedure cases and it has never produced this problem.
The research I did online points to basically one of two reasons:
1) I am trying to update or insert a date/time value that is not formatted correctly into a SQL Server 2005 table
2) I am trying to insert a, for example, CHAR(60) string into a CHAR(50) field.
Reason one is not applicable here since I am not using dates (in datetime format at least).
Reason two seemed to be the most likely issue. So I did a series of Response.Write() to spit out the objField.Name, objField.Type, objField.ActualSize, and if it was a numeric field the objField.Precision and objField.NumericScale.
Let us say that the stored SQL procedure is called twice as I am querying for values that are occurring in the same time frame but 2 different states. The loop I have in the ASP page does a For Each on the state in the state list and calls the stored procedure for each of the elements in the state list. I then call the MergeRecordSets function so it combines the 2 results into one. The general rule is that the data types and sizes of the columns in each resultset must be the same. With my Response.Write() checks of each of the columns returned in the 2 data sets I have found that they are identical. Doing my checks I also found that it breaks on the first column that is a NUMERIC column. The previous columns it was OK with were all CHAR or VARCHAR.
Is there any other reason why this error would come up?
The following is how I am calling the record merger function. The oQueryResult is going to be the final output (the combined records). objSingleRS is the result set returned by the stored procedure.
If oQueryResult Is Nothing Then
Set oQueryResult = objSingleRS
Else
Set oQueryResult = MergeRecordSets(Array(oQueryResult, objSingleRS))
End If
Here is the merge function. The line in which the code breaks is marked below.
Function MergeRecordSets(arrRecordsets)
Dim x, y, objCurrentRS
Dim objMergedRecordSet, objField, blnExists
Set objMergedRecordSet = Server.CreateObject("ADODB.Recordset")
For x=0 To UBound(arrRecordsets)
Set objCurrentRS = arrRecordsets(x)
For Each objField In objCurrentRS.Fields
blnExists = False
For y=0 To objMergedRecordSet.Fields.Count-1
If LCase(objMergedRecordSet.Fields(y).Name) = Lcase(objField.Name) Then
blnExists = True : Exit For
End If
Next
If Not(blnExists) Then
objMergedRecordSet.Fields.Append objField.Name, objField.Type, objField.DefinedSize
'objMergedRecordSet.Fields(objMergedRecordset.Fields.Count-1).Attributes = 32 'adFldIsNullable
End If
Next
Next
objMergedRecordSet.Open
For x=0 To UBound(arrRecordsets)
Set objCurrentRS = arrRecordsets(x)
Do Until objCurrentRS.EOF
objMergedRecordSet.AddNew
For Each objField In objCurrentRS.Fields
If Not(IsNull(objField.Value)) Then
'Response.Write(objField.Name & "<br>")
'Response.Write(objField.Type & "<br>")
objMergedRecordSet.Fields(objField.Name).Value = objField.Value 'Here is where it throws the Error.
End If
Next
objCurrentRS.MoveNext
Loop
Next
objMergedRecordSet.MoveFirst
Set MergeRecordSets = objMergedRecordSet
End Function
Here is the full error message returned:
Microsoft Cursor Engine error '80040e21'
Multiple-step operation generated errors. Check each status value.
/includes/funcs/Common.asp, line 4109
You mentioned that you have numeric columns, but you never set the Precision and NumericScale properties when you create the new Field in objMergedRecordSet. You need to set these properties for adNumeric and adDecimal fields.
objMergedRecordSet.Fields.Append objField.Name, objField.Type, objField.DefinedSize
With objMergedRecordSet.Fields(objField.Name)
.Precision = objField.Precision
.NumericScale = objField.NumericScale
End With
Also make sure you are not trying to put a NULL into a column that will not accept a NULL value. There is also the possibility of a type mismatch to cause this error so make sure you are passing a numeric value.
- Freddo