Not Creating the File when source has 0 rows - sql-server

I have the below within the Data-flow area. The problem I'm experiencing is that even if the result is 0, it is still creating the file.
Can anyone see what I'm doing wrong here?

This is pretty much expected and known annoying behavior.
SSIS will create an empty flat file, even if unchecked: "column names in a first data row".
The workarounds are:
remove such file by a file system task if #RowCountWriteOff = 0 just after the execution of a dataflow.
as alternative, do not start a dataflow if expected number of rows in the source is 0:
Update 2019-02-11:
Issue I have is that I have 13 of these export to csv commands in the
data flow and they are costly queries
Then double querying a source to check a row-count ahead will be even more expensive and perhaps better to reuse a value of variable #RowCountWriteOff.
Initial design has 13 dataflows, adding 13 constraints and 13 filesystem tasks the main control flow will make package more complex and harder to maintain
Therefore, suggestion is to use a OnPostExecute event handler, so cleanup logic is isolated to some certain dataflow:

Update 1 - Adding more details based on OP comments
Based on your comment i will assume that you want to loop over many tables using SQL Commands, check if table contains row, if so then you should export rows to flat files, else you should ignore the tables. I will mention the steps that you need to achieve that and provide links that contains more details for each step.
First you should create a Foreach Loop container to loop over tables
You should add an Execute SQL Task with a count command SELECT COunt(*) FROM ....) and store the Resultset inside a variable
Add a Data Flow Task that import data from OLEDB Source to Flat File Destination.
After that you should add a precedence constraint with expression, to the Data Flow Task, with expression similar to #[User::RowCount] > 0
Also, it is good to check the links i provided because they contains a lot of useful informations and step by step guides.
Initial Answer
Preventing SSIS from creating empty flat files is a common issue that you can find a lot of references online, there are many workarounds suggested and many methods that may solves the issue:
Try to set the Data Flow Task Delay Validation property to True
Create another Data Flow Task within the package, which will be used only to count rows in the Source, if it is bigger than 0 then the precedence constraint should led to the other Data Flow Task
Add a File System Task after the Data Flow Task which delete the output file if RowCount is o, you should set the precedence constraint expression to ensure that.
References and helpful links
How to prevent SSIS package creating empty flat file at the destination
Prevent SSIS from creating an empty flat file
Eliminating Empty Output Files in SSIS
Prevent SSIS for creating an empty csv file at destination
Check for number of rows returned and do not create empty destination file
Set the Data Flow Task Delay Validation property to True

Related

Does adding simple script tasks to SSIS packages drastically reduce performance?

I am creating an SSIS package to import CSV file data into a SQL Server table.
Some of the rows in the CSV files will have missing values.
For example, if a row has the format: value1,value2,value3 and value2 is missing,
then it will render as: value1,,value3 in the csv file.
When the above happens (value2 is missing) in my SSIS package, I want NULL to go into the receiving SQL Server column that would hold value2.
I understand that I can add a "Script" task to my SSIS package to apply this rule. However, I'm concerned that this will drastically reduce the performance of my SSIS package. I'm not an expert on the inner workings of SSIS/SQL Server, but I'm concerned that this script will cause my script to lose "BULK INSERT" capabilities (and other efficiencies) since the script will have to inspect every row and apply the changes as needed.
Can anyone confirm if adding such a script will cause major performance impacts? Or does the SSIS/SQL-Server engine run the script on every row and then bulk-insert? Is there another way I can apply this rule without taking a performance hit?
Firstly, you can use script task when required. Script task will be executed only once for each execution of the whole package not for every row. For every row there is another component called script component. When the other regular SSIS tasks are not enough to achieve what you want you can surely use script component. I don't believe it is a performance killer unless you implement it badly.
Secondly, this particular requirement you can simply use Flat File Source task to import your csv file. It will put the value NULL when there is no value. I'm considering this is a valid csv value and each row has correct number of comma for every fields (total field - 1 actually) even if value is empty or null for some fields.

Is there a way to ignore mapping errors in SSIS?

I have a data flow in SSIS that's using an ODBC Source to a conditional split.
The source returns a dynamic set of columns dependent on availability of data in the source - the number of columns goes from 1 to 13.
In my conditional split I have it pointing at the source and feeding the data to a destination that fits its number of columns.
Example:
Condition 1 -> Map column 1 to column 1 and ignore the other 12 columns
Condition 2 -> Map column 1 and 2 to column 1 and 2 and ignore the other 11 columns
However, if the source only contains 1 column it fails on the second condition because "there are some mapping errors on this path"
I know that the count of columns will never exceed 13 which means I can set conditions for columns 1 - 13.
Is there any way that I can ignore the mapping error or force SSIS to stop at the last executable case in my conditional split?
I don't personally want to have to dive into a script component so if this can be done with conditional split I'd be relieved!
Any thoughts?
As Larnu indicates, the number of columns in a data flow is a design time artifact and cannot be changed at run-time.
But, you should be able to handle this with 12 data flows.
Execute SQL Task -> However your current ODBC source is generating a variable set of columns, determine how many are being returned. Assign this to an SSIS Variable #[User::ColumnCount]
Attach 12 output paths from the Execute SQL Task to custom Data Flow Tasks that account for the number of source columns.
Change the precedence constraint on each of the paths to be Constraint and Expression with expressions like #[User::ColumnCount]==1 ... ==13
The SSIS designer is going to try to validate metadata as you design the package. As will the execution engine when you run the package. Therefore, you'll need to set the Delay Validation property to True on each of the Data Flow Tasks after you finish designing them.
In fact, as I think about this more, you'd like be better served by a parent/child package paradigm here. Design a package per data flow task and then have the parent/controller package invoke them much as I described above. That should simplify the metadata validation challenges you'll experience trying to get this built.

SSIS redirect empty rows as flat file source read errors

I'm struggling to find a built-in way to redirect empty rows as flat file source read errors in SSIS (without resorting to a custom script task).
as an example, you could have a source file with an empty row in the middle of it:
DATE,CURRENCY_NAME
2017-13-04,"US Dollar"
2017-11-04,"Pound Sterling"
2017-11-04,"Aus Dollar"
and your column types defined as:
DATE: database time [DT_DBTIME]
CURRENCY_NAME: string [DT_STR]
with all that, package still runs and takes the empty row all the way to destination where it, naturally fails. I was to be able to catch it early and identify as a source read failure. Is it possible w/o a script task? A simple derived column perhaps but I would prefer if this could be configured at the Connection Manager / Flat File Source level.
The only way to not rely on a script task is to define your source flat file with only one varchar(max) column, chose a delimiter that is never used within and write all the content into a SQL Server staging table. You can then clean those empty lines and parse the rest to a relational output using SQL.
This approach is not very clean and a takes lot more effort than using a script task to dump empty lines or ones not matching a pattern. It isn't that hard to create a transformation with the script component
This being said, my advise is to document a clear interface description and distribute it to all clients using your interface. Handle all files that throw an error while reading the flat file and send a mail with the file to the responsible client with information that it doesn't follow the interface rules and needs to be fixed.
Just imagine the flat file is manually generated, even worse using something like excel, you will struggle with wrong file encoding, missing columns, non ascii characters, wrong date format etc.
You will be working on handling all exceptions caused by quality issues.
Just add a Conditional Split component, and use the following expression to split rows
[DATE] == ""
And connect the default output connector to the destination
References
Conditional Split Transformation

SQL Server 2016 SSIS Conditionally Overwrite Text File

Image the following scenario:
1. there are N number of jobs
2. the jobs write data to the same file once a day sequentially
3. task setting indicates whether the file should be overwritten or appended to
what i've tried thus far is using a conditional split in my data flow:
to test it out, the Case 1 & 2 are:
what actually happens is, conditional split tries to work out which data rows to send where, ends up sending all rows to one side and 0 rows to the other and both sides end up opening the file (i think), hence the errors:
i get that i'm misusing the conditional split here, but come one, it's 2017 outside, the must be a way to do this without resorting to Script tasks clearing the files?
Your problem - you are misusing Conditional Split; it is designed to manipulate data rows in a data flow and you are trying to manage control flow. Speaking of SSIS, it does not know in advance that you will use only one of Flat File Destinations; it tries to initialize both. By doing so SSIS tries to open the same file from two Destinations and fails with an error.
You can handle the task the SSIS way - manage control flow with tasks. In your case, the destination file should be appended or being overwritten. But the being overwritten can be viewed as being overwritten with zero lines and then being appended. Luckily for you, SSIS overwrites a file event no records are coming from a Data Flow.
So, before your dataflow which should always append data, you create another dataflow which always receives ZERO lines of data (columns in the set can be arbitrary) and Flat File Destination overwriting the file. Then use conditional execution of control flow with precedence constrains to execute this "File Cleanup DataFlow Task". You might also need to set DelayValidation=true on this "File Cleanup DataFlow Task".

SSIS trying to only load file if all rows are good

I am trying to use a SSIS package to insert data from a file into a table but only if all the data in the file is good. I have read around and realise that I can split my good data and bad data with a conditional split.
However I cannot come up with a way to not write the good data if there is some bad data rows.
I can solve my problem use a staging table. I just thought I would ask if I am missing a more elegant way to do this within SSIS package rather than load then transform with TSQL.
Thanks
SSIS way allows wrapping actions in a Transaction. According to your task, you need to count bad rows in the dataflow, and if there is at least one bad row - do nothing i.e. rollback.
Below is how I would do it in Pure SSIS. Create a sequence and specify TransactionOption=Required on it, move your dataflow to the sequence. Add Count Rows transformation to your bad rows dataflow and store its result to some variable. After DataFlow inside sequence - create conditional task link where you check whether bad_rowcount variable > 0, and on the next - do little script task which raise an error to roll back transaction.
Pure SSIS - yes! Simpler than using staging table - not sure.

Resources