In my SSIS pacakge I have an Execute SQL Task with 2 statements:
statement 1:
select coalesce ( max (id), 0)+1 as ID from AAA
statement 2:
Insert into BBB (id) values (?)
In the first statement, I saved the result to an variable ID, and in the 2nd statement, I use this variable ID to insert into BBB id column. Let's say the result of the first statement should be 4, however, after I query table BBB, i found what inserted into BBB is 0.
Did I miss anything here?
Running the first statement generates the result of 1 for an empty table.
The default value for an integer in SSIS is going to be 0.
It would lead me to believe that you are not assigning the result from an Execute SQL Task properly.
Either drop in an Script Task to print the value via information events
public void Main()
{
bool fireAgain = false;
string message = "{0}::{1} : {2}";
foreach (var item in Dts.Variables)
{
Dts.Events.FireInformation(0, "SCR Echo Back", string.Format(message, item.Namespace, item.Name, item.Value), string.Empty, 0, ref fireAgain);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Or set a breakpoint on the second Execute SQL Task to identify the current value of the variable.
If the value is set correctly, then the only remaining point of failure is the second Execute SQL Task where it would imply you do not have your variable mapped.
As your code sample uses a question mark ? as the place holder, it becomes a question of whether the connection manager is OLEDB in which we have a zero based ordinal system or ODBC in which we have a one based ordinal.
If the problem exists on the first step, then be certain that you have used the correct 0/1 value as the "name" of the result column
Related
When I execute a SQL query from Java and store the boolean returned, the query always returns true which shouldn't be the case at all. So I emptied the table and fired the query again, and yet it returns true for the emptied table. I have attached a picture of the table. I want the query to return true or false, so I can store it in Java. Can someone please specify an alternate code for this, please?
This is my code on java for the query.
boolean avail = st.execute("SELECT EXISTS(SELECT * from sales WHERE product='"+n+"' AND ord_date='"+sqlDate+"');");
And this is my code for result set
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
This is the table, name of the table is 'sales'
I'm new to MySQL, a more specific approach is appreciated.
Statement.execute will return true regardless of what the query returns. You are still supposed to retrieve the actual result of the query.
Returns
true if the first result is a ResultSet object; false if it is an update count or there are no results
As you execute an EXISTS statement, there will always be a result (true or false). The actual value still has to be retrieved:
You must then use the methods getResultSet or getUpdateCount to retrieve the result, and getMoreResults to move to any subsequent result(s).
For reference: https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#execute-java.lang.String-String
Also note that you are directly embedding strings into your query, this will leave you vulnerable to SQL injections. Please read: How can prepared statements protect from SQL injection attacks?. Recommended reading: Introduction to JDBC
The return value of Statement.execute() signals whether the query produces a result set (true) or - possibly - an update count (false). The query you execute is a select which will always produce a result set (even if empty). In other words, it will always return true for a select.
If you want to get the result of your query, then the recommend approach is to use executeQuery. However, you are also concatenating values into your query string, which is a bad idea because it leave you vulnerable to SQL injection. The recommended approach is to switch to prepared statements:
try (PreparedStatement pstmt = con.prepareStatement(
"SELECT EXISTS(SELECT * from sales WHERE product = ? AND ord_date = ?)")) {
pstmt.setString(1, n);
pstmt.setDate(2, sqlDate);
try (ResultSet rs = st.executeQuery() {
boolean avail = rs.next() && rs.getBoolean(1);
// use avail...
}
}
I have a field that stores a numeric value that will go from 0 to 7. It is a counter for some steps to be completed in the application. Each time a step is completed, the counter is updated with the new value. User can go back on the steps and then forward. If he has completed step 3, he can go back to step 1 and then forward till step 3 again. What I want to do is to avoid that when the user returns to step 3 the counter gets updated with 1 and 2 values but remains 3. I want to investigate a way to do it within the update query.
The query is the following:
try{
$pdo->query("UPDATE ruolo SET wiz_step='$step' WHERE id_user='$utente'");
}
catch(PDOException $e){
$status='500';
$data['step']=$step;
$message='Si รจ verificato un errore. Abbiamo aperto una segnalazione al team tecnico.';
}
$message="Step aggiornato correttamente";
}
Is it possible to tell mysql to update wiz_step only if $step is > than the value of wiz_step before the update?
Table structure is just made of three int fields: id primary and autoincrement, id_user and wiz_step.
Note: I assume I am not open to mysql injections since none of the values in the query are coming from a user input. They are all set by the php logic.
As these are all values controlled by code it is quite simple to do, also change to using prepared queries to protect your code from SQL Injection Attack
try{
$data = [':step' => $step, ':step1' => $step, ':uid' => $utente];
$stmt = $pdo->prepare("UPDATE ruolo
SET wiz_step=:step
WHERE id_user=:uid
AND :step1 > wiz_step");
$stmt->execute($data);
}
Here's a slight variation on the answer from #RiggsFolly:
try{
$data = ['step' => $step, 'uid' => $utente];
$stmt = $pdo->prepare("UPDATE ruolo
SET wiz_step=GREATEST(:step, wiz_step)
WHERE id_user=:uid");
$stmt->execute($data);
}
See the GREATEST() function in the MySQL manual. It returns the greater value of its arguments. So if the parameter is greater, it will be used to update the column. If the existing value is greater, then no change will be made, because wiz_step = wiz_step is a no-op.
P.S.: It's not necessary to use the : character in the array keys when you pass parameters to a prepared query. It was needed in an early version of PDO long ago, but not anymore.
I'm working on a SSIS package where I have a text file with 5 columns. I need to check if all the rows for 5th column are NULL values.
If all the rows in 5th column are NULL then all the data should go for invalid file table.
If any row in 5th column have non NULL value then all the data should go to valid table.
You will need to read the entire file before being able to make the decision of where to write it to, so introduce a third table where you can stage the data first
Next part would be to build the logic that checks the staging table for all NULLS. Below query would return 0 if all was NULL and more than 0 if any record had a value
SELECT COUNT(*) FROM dbo.StagingTable ST WHERE ST.Column5 IS NOT NULL
Once you feed the answer into a variable you can use precedence constraints to fire the dataflow copy [staging to active] if the result was more than 0 or [staging to faulty] if the result was 0
personally if i had to perform this task I would use a script task to do it all:
Load into a data table
Use linq to check column to determine destination .Where(x => x[4]!=null).Count()
Load to destination via bulk Copy
You can check if the file is empty with C# using an OleDbDataAdapter and search the file, then determine where to load the file using SSIS Precedence Constraints. This example uses a CSV file without column names. If the columns do have names add the replacement code noted in the comments below. You will also need the using statements listed.
Add an SSIS Boolean variable. This is IsColumnNull in the following example. Next add a C# Script Task with IsColumnNull variable in the ReadWriteVariables field, and (optionally) a variable holding the file path ReadOnlyVariables pane.
Next set Precedence Constraints to check for both a true condition (has null rows) or false condition (does not have null records). Since the IsColumnNull variable is a Boolean, use just the variable itself as the expression to check for all null rows, but add ! for non-nulls, i.e. !#[User::IsColumnNull].
Connect the appropriate Data Flow Tasks with each destination table to the corresponding Precedence Constraint. For example, add the Data Flow Task with the "invalid file table" as the destination after the Precedence Constraint checking for a true value in the IsColumnNull variable.
Precedence Constraint For Rows with Nulls:
Precedence Constraint for Rows without Nulls:
Script Task Example:
using System;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Linq;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
string fullFilePath = Dts.Variables["User::FilePath"].Value.ToString();
string fileName = Path.GetFileName(fullFilePath);
string filePath = Path.GetDirectoryName(fullFilePath);
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath
+ ";Extended Properties=\"text;HDR=No;FMT=Delimited\";";
//add filter for NOT NULL on given column to only return non-nulls
string sql = "SELECT F2 FROM " + fileName + " WHERE F2 IS NOT NULL";
//if file has column names replce "connStr" and "sql" as shown below
/*
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath
+ ";Extended Properties=\"text;HDR=Yes;FMT=Delimited\";";
string sql = "SELECT ID FROM " + fileName + " WHERE ID IS NOT NULL";
*/
using (OleDbDataAdapter oleAdpt = new OleDbDataAdapter(sql, connStr))
{
DataTable dt = new DataTable();
oleAdpt.Fill(dt);
//if emtpy set IsColumnNull SSIS variable to true
if (dt.Select().Count() < 1)
{
Dts.Variables["User::IsColumnNull"].Value = true;
}
else
{
Dts.Variables["User::IsColumnNull"].Value = false;
}
}
New to SSIS, been dealing with SSMS mostly. Anyone can help translating the below SSMS statement into SSIS Derived Column Transformation? Many thanks.
ReliabilityFactorInput = Case
When (isnull(pn.LBOXMATL, 'OTHER') = 'OTHER' AND (round(ISNull(edd.cal_year, eqd.YearManuf) + 1, -4)/10000<=2003) OR pn.LBOXMATL ='Cast Iron') AND (ceiling((pn.NOWAYS+1)/2)*2 >= 4) then '1.3'
When (isnull(pn.LBOXMATL, 'OTHER') = 'OTHER' AND (round(ISNull(edd.cal_year, eqd.YearManuf) + 1, -4)/10000<=2003) OR pn.LBOXMATL = 'Cast Iron') AND (ceiling((pn.NOWAYS+1)/2)*2 < 4) then '1.1'
else ''
End
1.Name a variable with whatever name you want with int data type
2.Use execute sql task
3.copy all the complete query into that task and specify the result Set to single row
4.Switch to Result Set page, choose the variable you create, and set the result name to 0
5.Now every time you run the package the variable will be assigned either 1.3 or 1.1
That variable could be used in Derived Column transformation in data flow now
Not sure where the problem is here... I have a stored procedure written that (when executed within SQL Server Mgmt. Studio) returns results I expect to see:
USE [DataViewer]
GO
/****** Object: StoredProcedure [dbo].[DV_GetPSCTreeNodes] Script Date: 08/10/2014 1:48:03 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Me!>
-- Description: <Used by data viewer GUI.>
-- =============================================
ALTER PROCEDURE [dbo].[DV_GetPSCTreeNodes]
-- Add the parameters for the stored procedure here
#iNodeLevel int,
#iParentNodeId bigint
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sQuery varchar (2000)
IF #iNodeLevel >= 5
RETURN
ELSE
-- Insert statements for procedure here
SET #sQuery = 'SELECT * FROM DataView.dbo.v_Tree
WHERE L' + CAST((#iNodeLevel + 1) AS VARCHAR(10)) + 'ID IS NULL
AND L' + CAST((#iNodeLevel) AS VARCHAR(10)) + 'ID = ' + CAST((#iParentNodeId)
AS VARCHAR(10))
EXEC (#sQuery)
END
As mentioned, if I run this in SMSS, I get the expected results.
However, if I run this through the service I have set up, I get the correct amount of records back, but they are all duplicates of the first row (and I can look at the table and know I am getting duplicates). If I try new params and get 15 distinct rows back in SSMS, my webpage will show 15 rows of repeated row 1 data.
Here is the call from my Client:
List<v_PowerSystemCIMTree> list = null;
DVServiceClient proxy = new DVServiceClient();
try
{
list = proxy.DV_GetPSCTreeNodes(2,325550).ToList(); //2 and 325550 are just hardcoded to
//check to see if it's working
}
catch (Exception ex)
{
Console.WriteLine(ex.GetType().FullName);
Console.WriteLine(ex.Message);
}
finally
{
proxy.Close();
}
return View(list);
Which calls my Service:
readonly DataViewerEntities _Context = new DataViewerEntities();
public List<DataViewer_DAL.v_PowerSystemCIMTree> DV_GetPSCTreeNodes(int firstParam,
long secondParam)
{
return _Context.DV_GetPSCTreeNodes(firstParam,secondParam).ToList();
}
Why the heck would I get one result set in the Management Studio, but repeated data on my webpage?
Known issue: since you're selecting from a view which doesn't have a defined primary key, Entity Framework will use all non-nullable columns as the "entity key".
If EF reads a second row from the view that has the same entity key (same values in all non-nullable columns), it will just repeat the first row already read - it will not look at the other, remaining columns....
So you just need to either add the primary key for the underlying table(s) to the view's columns, tweak the EF data model to explicitly define an "entity key" for the view, or you need to add an artificial, unique column (like a ROW_NUMBER()) to your view and make sure it's non-nullable and thus part of the EF "derived" entity key