SSIS - how to capture PRINT message? - sql-server

The Execute SQL task calls a procedure that has a PRINT command inside. How can I display these messages at once in the progress tab (or in output)?

You will need to write your own process for invoking SQL as the Execute SQL Task does not have the event handler defined for the side channel communication.
I would go at it from a Script Task
Setup
In my database, I have a stored procedure defined as the following
CREATE OR ALTER PROCEDURE dbo.Printsalot
AS
BEGIN
SET NOCOUNT ON;
RAISERROR('This is the first message', 10, 1) WITH NOWAIT;
WAITFOR DELAY '00:00:05';
RAISERROR('This is the second message', 10, 1) WITH NOWAIT;
WAITFOR DELAY '00:00:04';
RAISERROR('This is the third message', 10, 1) WITH NOWAIT;
WAITFOR DELAY '00:00:03';
RAISERROR('This is the fourth message', 10, 1) WITH NOWAIT;
WAITFOR DELAY '00:00:02';
RAISERROR('This is the fifth message', 10, 1) WITH NOWAIT;
WAITFOR DELAY '00:00:01';
RAISERROR('This is the sixth message', 10, 1) WITH NOWAIT;
END;
I use RAISERROR instead of print so I can WITH NOWAIT otherwise, the PRINT isn't going to be so useful. And I put delays in there to simulate a longer running process.
Script Task
Your TODO with the following code
Define connString appropriately. I've never had much luck tying into the existing connection managers in a script task so I typically use a C# variable to hold the connection string info and pass that into the script
Define a CommandTimeout on your command object if the proc takes too long
Define proc appropriately
And code
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
namespace ST_ExecuteSQLWithInfo
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
// TODO: Fix this
string connString = #"SERVER=.\dev2017;Integrated Security=true;DATABASE=tempdb";
// TODO: Fix this
string proc = "dbo.Printsalot";
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
connection.FireInfoMessageEventOnUserErrors = true;
connection.InfoMessage += new SqlInfoMessageEventHandler(HandleSqlProgress);
using (SqlCommand command = new SqlCommand(proc, connection))
{
command.CommandType = CommandType.StoredProcedure;
// TODO: Define a command.CommandTimeout value
command.ExecuteNonQuery();
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
public void HandleSqlProgress(object sender, SqlInfoMessageEventArgs e)
{
bool fireAgain = true;
Dts.Events.FireInformation(0, "SQL Progress", e.Message, "", 0, ref fireAgain);
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
Results
From the output window/Progress window
SSIS package "C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\SO_71109444.dtsx" starting.
Information: 0x0 at SCR Echo Proc, SQL Progress: This is the first message
Information: 0x0 at SCR Echo Proc, SQL Progress: This is the second message
Information: 0x0 at SCR Echo Proc, SQL Progress: This is the third message
Information: 0x0 at SCR Echo Proc, SQL Progress: This is the fourth message
Information: 0x0 at SCR Echo Proc, SQL Progress: This is the fifth message
Information: 0x0 at SCR Echo Proc, SQL Progress: This is the sixth message
SSIS package "C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\SO_71109444.dtsx" finished: Success.
References
http://www.sqlskills.com/blogs/jonathan/capturing-infomessage-output-print-raiserror-from-sql-server-using-powershell/
https://stackoverflow.com/a/349362/181965
c# - SqlConnection InfoMessage triggering only at end of execution
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlinfomessageeventhandler
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlconnection.infomessage
https://dba.stackexchange.com/q/54544/2131

Related

asynchronous stored procedure in snowflake

I need to have stored procedure in snowflake that has to be executed in asynchronous mode .so if call is made is to the stored procedure ,it should immediately return queryid and close the session. The actual execution should happen independently. I tried implementing the wrapper stored procedure that calls asynchronous stored procedure but doesn't seem to work.
You can execute a stored procedure asynchronous from your Java app:
https://docs.snowflake.com/en/user-guide/jdbc-using.html#examples-of-asynchronous-queries
I created a simple stored procedure which waits 5 seconds and then return "Success". Here is a sample Java code to call the stored procedure, and get the query ID (while the stored procedure is still working):
public static void main(String[] args) throws SQLException, InterruptedException {
try (Connection con = getConnection()) {
try (var statement = con.createStatement()) {
var sql_command = "CALL TEST_SP()";
var resultSet = statement.unwrap(SnowflakeStatement.class).executeAsyncQuery(sql_command);
var queryID = resultSet.unwrap(SnowflakeResultSet.class).getQueryID();
System.out.printf("Calling TEST_SP() - Query ID is %s%n", queryID);
var queryStatus = resultSet.unwrap(SnowflakeResultSet.class).getStatus();
while (queryStatus == QueryStatus.RUNNING || queryStatus == QueryStatus.RESUMING_WAREHOUSE) {
Thread.sleep(1000); // 1000 milliseconds.
System.out.printf( "Waiting for 1 second...\n");
queryStatus = resultSet.unwrap(SnowflakeResultSet.class).getStatus();
}
if (resultSet.next()) System.out.println(resultSet.getString(1));
}
}
}
Output:
Calling TEST_SP() - Query ID is 019b08ac-32c3-3514-0000-b4550004911a
Waiting for 1 second...
Waiting for 1 second...
Waiting for 1 second...
Waiting for 1 second...
Waiting for 1 second...
Success
Of course, you don't need to wait until the end of the stored procedure, this code just shows that how the stored procedure is executed asynchronously.

Spring boot jpa not catching exception when exception is thrown while executing procedure using entity manager

I have a procedure in SQL Server and I am executing that procedure using entity manager in spring boot application.
When an exception is thrown in that procedure, the method which it is executing that procedure is not catching the exception (I have included persistence exception in catch block).
Any help would be really appreciated.
#Configuration
public class SampleOperations {
#Autowired
#PersistenceContext(unitName = "SampleUnit")
#Qualifier("SampleEntityManagerFactory")
private EntityManager entityMgr;
public void method1(DModel mapObject) throws CustomException {
boolean queryStatus = false;
try {
StoredProcedureQuery sp = entityMgr.createStoredProcedureQuery("proc_clean_current_version_tables");
sp.registerStoredProcedureParameter(1, String.class, ParameterMode.IN);
sp.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
sp.setParameter(1, mapObject.getCountry());
sp.setParameter(2, mapObject.getVersion());
sp.execute();
entityMgr.close();
} catch (IllegalArgumentException | PersistenceException e) {
throw new Customxception(
"Unable to execute procedure ");
}
}
}
SQL server procedure
BEGIN TRY
DROP TABLE IF EXISTS #get_col_hdr;
CREATE TABLE #get_col_hdr(colName VARCHAR(MAX));
INSERT INTO #get_col_hdr
EXEC proc_get_column_header
#tableId,
#cntr;
SELECT #columnHeader = colName
FROM #get_col_hdr;
END TRY
BEGIN CATCH
set #error_message = 'Unable to import tables from databases
.'+ERROR_MESSAGE();
THROW 60000, #error_message, 1;
END CATCH

MSSQL and JDBC read DBCC USEROPTIONS

I am trying to read some of the attributes returned by following command
DBCC USEROPTIONS
How to use following command in JDBC?
List<ResultVO> list = getJdbcTemplate().query(sql, new ParameterizedBeanPropertyRowMapper<ResultVO>() {
#Override
public ResultVO mapRow(ResultSet rs, int rowNumber) throws SQLException {
System.out.println(rowNumber);
ResultVO v = new ResultVO();
v.setSetOption(rs.getString(0));
v.setValue(rs.getString(1));
//--
return v;
}
}, (List<String>) null);
It throws exception as follows:
Caused by: org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [SELECT DBCC USEROPTIONS]; The index 1 is out of range.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The index 1 is out of range.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:106)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
The first line of the error message indicates that your code tried to execute the SQL statement
SELECT DBCC USEROPTIONS
but that is not valid T-SQL syntax. The T-SQL statement
DBCC USEROPTIONS
does return a valid ResultSet, as illustrated by the following vanilla JDBC code:
try (Connection conn = DriverManager.getConnection(connectionUrl)) {
try (
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("DBCC USEROPTIONS")) {
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
System.out.printf("[%s]: %s%n", rsmd.getColumnName(i), rsmd.getColumnTypeName(i));
}
System.out.println();
while (rs.next()) {
System.out.printf("%s: %s%n", rs.getString(1), rs.getString(2));
}
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
which produces
[Set Option]: nvarchar
[Value]: nvarchar
textsize: -1
language: us_english
dateformat: mdy
datefirst: 7
lock_timeout: -1
quoted_identifier: SET
ansi_null_dflt_on: SET
ansi_warnings: SET
ansi_padding: SET
ansi_nulls: SET
concat_null_yields_null: SET
isolation level: read committed
It looks like you need to adjust your Spring JDBC code to just execute DBCC USEROPTIONS.

RollBack insert to multiple tables in SQL Server 2005

I want to use Transaction and rollback first time but I am confused as if how to in my case?
I want to insert records in multiple tables and I need to use for loop to insert more than one record in one table. And also I want to delete all records from all tables if some error occurred.
Let's take 3 tables as an example:
Insert into table1 values (a, b, c);
for(int i = 0; i < gridview1.rows.count; i++)
{
Insert into table 2 values (i, b, c);
}
Insert into table 3 values (a, b, c);
So this is just a short example of what I want. I tried few tutorials but those seems to be for different cases and pretty easy.
I have to use SQL Server 2005 and cannot go to 2008 or above..
Thanks in advance
Edit
Currently I am doing this using multiple stored procedure (one for each table) And I want to implement a transaction in it. Using Asp.net if possible will also be ok for me.
This is very basic ADO.NET - you need to set up your connection and transaction, and then you need three commands that "participate" in that transaction. You execute your commands, and if all goes well, you commit the transaction. If anything fails, a try...catch will kick in and roll back the transaction to the state before this all started.
Code will look something like this:
// set up your connection
using (SqlConnection conn = new SqlConnection("--your-connection-string-here--"))
{
// start a transaction
using (SqlTransaction transaction = conn.BeginTransaction())
{
try
{
conn.Open();
// create a command for your first stored procedure
// and make sure it uses the transaction from above
using (SqlCommand cmdProc1 = new SqlCommand("dbo.Procedure1Name", conn, transaction))
{
// set the parameters
cmdProc1.Parameters.Add("#ParamA", SqlDbType.Int).Value = a;
cmdProc1.Parameters.Add("#ParamB", SqlDbType.Int).Value = b;
cmdProc1.Parameters.Add("#ParamC", SqlDbType.Int).Value = c;
// execute stored procedure
cmdProc1.ExecuteNonQuery();
}
// create a command for your second stored procedure
// and make sure it uses the transaction from above
using (SqlCommand cmdProc2 = new SqlCommand("dbo.Procedure2Name", conn, transaction))
{
// set the parameters
cmdProc2.Parameters.Add("#ParamI", SqlDbType.Int);
cmdProc2.Parameters.Add("#ParamB", SqlDbType.Int);
cmdProc2.Parameters.Add("#ParamC", SqlDbType.Int);
// loop and set parameter values
for (int i = 0; i < gridview1.rows.count; i++)
{
cmdProc2.Parameters["#ParamI"].Value = i;
cmdProc2.Parameters["#ParamB"].Value = b;
cmdProc2.Parameters["#ParamC"].Value = c;
cmdProc2.ExecuteNonQuery();
}
}
// create a command for your third stored procedure
// and make sure it uses the transaction from above
using (SqlCommand cmdProc3 = new SqlCommand("dbo.Procedure3Name", conn, transaction))
{
// set the parameters
cmdProc3.Parameters.Add("#ParamA", SqlDbType.Int).Value = a;
cmdProc3.Parameters.Add("#ParamB", SqlDbType.Int).Value = b;
cmdProc3.Parameters.Add("#ParamC", SqlDbType.Int).Value = c;
// execute stored procedure
cmdProc3.ExecuteNonQuery();
}
// if everything went well - commit the transaction!
transaction.Commit();
}
catch (Exception exc)
{
// log the exception, rollback the transaction
transaction.Rollback();
}
}
}

SQL Try Catch for specific severity only

Hi I have a long SQL script which runs as a single transaction to bulk import from files.
When running the script I am finding that I get some informational messages, some warnings and then some errors that immediately halt the running of the script - however it doesn't rollback the transaction.
To get around this I used a try-catch block which now successfully rolls back the transaction if there are any errors; however my info and warnings also trigger the catch block and stop my script when it needent have done.
Is there a way to only jump to the catch for critical errors, for the warnings and info messages I simply want to test ##error and insert it to a string then output these all to the user at the end.
Are you using RaiseError event?
severity level 0-9 should be used for informational level messages.
For more information
RaiseError
Database Engine Severity Levels
Try this,I hope it will give you solution
string cnnString =WebConfigurationManager.ConnectionStrings["MyString"].ConnectionString;
SqlConnection cnn = new SqlConnection(cnnString);
SqlTransaction transaction;
cnn.Open();
transaction = cnn.BeginTransaction();
try
{
// Command Objects for the transaction
SqlCommand cmd1 = new SqlCommand("sproc1", cnn);
SqlCommand cmd2 = new SqlCommand("sproc2", cnn);
cmd1.CommandType = CommandType.StoredProcedure;
cmd2.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.Add(new SqlParameter("#Param1", SqlDbType.NVarChar, 50));
cmd1.Parameters["#Param1"].Value = paramValue1;
cmd1.Parameters.Add(new SqlParameter("#Param2", SqlDbType.NVarChar, 50));
cmd1.Parameters["#Param2"].Value = paramValue2;
cmd2.Parameters.Add(new SqlParameter("#Param3", SqlDbType.NVarChar, 50));
cmd2.Parameters["#Param3"].Value = paramValue3;
cmd2.Parameters.Add(new SqlParameter("#Param4", SqlDbType.NVarChar, 50));
cmd2.Parameters["#Param4"].Value = paramValue4;
cmd2.Parameters.Add("#out", OleDbType.NVarCha);
myCommand.Parameters["#out"].Direction = ParameterDirection.Output;
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();
transaction.Commit();
}
catch (SqlException sqlExc)
{
foreach (SqlError error in sqlExc.Errors)
{
string errors = string.Format("{0}: ", error.Message);
cmd2.Parameters["#out"].Value) = errors;
transaction.Rollback();
}
}
finally
{
cnn.Close();
cnn.Dispose();
}

Resources