I am working in a migration project, where lift and shift method is used to migrate SQL server DB from onprem to AZure Cloud. There is a lot of stored procedures used for integration in On prem.Now here in On prem , to process the XMl file and execute the same procedures pointing to the cloud Db I need to write a code in Databricks. I have code to execute a single stored procedure using Scala, as I am new to coding in python/scala I couldn't find the right method to execute the procedures.
The below code is what I have used to execute one procedure- sample
%scala
val username = "xxxxx"
val pass = "xxxxx"
val url = "jdbc:sqlserver://xxx.database.windows.net:1433;databaseName=xxx"
val table = "SalesLT.Temp3"
val query = s"EXEC sp_truncate_table '${table}'"
val conn = DriverManager.getConnection(url, username, pass)
val rs = conn.createStatement.execute(query)
I have a requirement to execute some 10 stored procedures in series.
Looking forward for your suggestions.
To run multiple stored procedures sequentially you can create one Stored procedure and call all your stored procedures in that and call this stored procedure through Databricks.
The following code example is referred from here by #Thom A
CREATE PROC MySP1 #int int AS
PRINT #int / 0; --To error
GO
CREATE PROC MySP2 #int int AS
PRINT #int + 1;
GO
CREATE PROC MySP3 #int int AS
PRINT #int + 2;
GO
CREATE PROC AllMySPs #Int int AS
PRINT 'Executing SP1...';
BEGIN TRY
EXEC MySP1 #Int;
END TRY
BEGIN CATCH
PRINT 'MySP1 failed';
END CATCH
PRINT 'Executing SP2...';
BEGIN TRY
EXEC MySP2 #Int;
END TRY
BEGIN CATCH
PRINT 'MySP2 failed';
END CATCH
PRINT 'Executing SP3...';
BEGIN TRY
EXEC MySP3 #Int;
END TRY
BEGIN CATCH
PRINT 'MySP3 failed';
END CATCH
GO
CREATE OR ALTER FUNCTION sso.FINDSEQVALUE
(#sequence_text text)
RETURNS int
AS
BEGIN
DECLARE #value int;
DECLARE #sequence_value nvarchar(150);
SELECT #sequence_value = CAST(#sequence_text AS nvarchar(150));
SELECT #value = NEXT VALUE FOR #sequence_value;
RETURN #value;
END;
I have a problem. I have created a function on SQL Server and I defined the parameter as you can see. But I cannot add the this command #sequence_value after NEXT VALUE FOR command and I am getting an error.
Incorrect syntax near '#sequence_value'
Somebody can say that "You can use (SELECT NEXT VALUE FOR [SEQUENCE])". But I need this function because of there are two different database on my project. I need same function for databases. In addition function parameter need to be text.
What should I do?
I have a java front end that has a table of data. We need to save this data to the Database via stored procedure. If the passed parameter is a just an array, I am able to access the contents easily. But if the contents of the array is a also a row type, thats the part im having trouble with.
I dont know how to access the contents of the array.
Im using DB2 10.1
CREATE TABLE "TEST"."CHART_ACCT" (
"ACCT_NO" VARCHAR(10) NOT NULL,
"ACCT_DESC" VARCHAR(40) NOT NULL
)
ORGANIZE BY ROW
DATA CAPTURE NONE
IN "USERSPACE1"
COMPRESS YES ADAPTIVE
VALUE COMPRESSION#
CREATE OR REPLACE TYPE TEST.ACCT AS ROW ANCHOR ROW OF TEST.CHART_ACCT#
CREATE OR REPLACE TYPE TEST.ACCT_ARR AS TEST.ACCT ARRAY[]#
CREATE OR REPLACE PROCEDURE TEST.TEST_ARRAY (IN P_ACCT_ARR TEST.ACCT_ARR)
P1: BEGIN
-- #######################################################################
-- #
-- #######################################################################
DECLARE i INTEGER;
SET i = 1;
WHILE i < 10 DO
CALL DBMS_OUTPUT.PUT_LINE(P_GLACCT_ARR[i]);
set i = i + 1;
END WHILE;
END P1#
You need to declare a temporary variable of the row type and assign array elements to it in a loop:
CREATE OR REPLACE PROCEDURE TEST_ARRAY (IN P_ACCT_ARR ACCT_ARR)
P1: BEGIN
DECLARE i INTEGER;
DECLARE v_acct acct;
SET i = 1;
WHILE i < CARDINALITY(p_acct_arr) DO
SET v_acct = p_acct_arr[i];
CALL DBMS_OUTPUT.PUT_LINE('Account number = ' || v_acct.acct_no);
set i = i + 1;
END WHILE;
END P1#
However, a more concise way to do that is to use the collection-derived table reference:
CREATE OR REPLACE PROCEDURE TEST_ARRAY (IN P_ACCT_ARR ACCT_ARR)
P1: BEGIN
FOR r AS (SELECT * FROM UNNEST(p_acct_arr) t ) DO
CALL DBMS_OUTPUT.PUT_LINE('Account number = ' || r.acct_no);
END FOR;
END P1#
I have a stored procedure that works fine but it has inside it three "select"s.
The selects are not from an inner temporary table.
This is mainly the format of the procedure:
ALTER PROCEDURE [dbo].[STProce]
#param1 int,
#param2 int,
#param3 int,
#param4 int,
#param5 int
AS
select #param1 as p1, #param2 as p2, #param3 as p3
.
.
.
select #param4 as p4
.
.
.
select #param5 as p5
I'm executing the procedure from another procedure and need to catch it there.
I created a table and inserts into it the "exec" from the procedure, like that:
CREATE TABLE #stalledp
(
RowNumber INT,
fldid INT,
fldLastUpdated datetime,
fldCreationDate datetime,
fldName nvarchar(255),
fldPending nvarchar(255)
)
INSERT INTO #stalledp (RowNumber,fldid,fldLastUpdated,fldCreationDate,fldName,fldPending)
EXEC spDebuggerViews_GetStuckWorkflowInstances #workflowSpaceId='00000000-0000-0000-0000-000000000000',#pageNum=1,#pageSize=100000,#orderByColumn=N'fldid',#sortOrder=1,#workflowInstanceId=0,#stuckInstanceType=1,#createdDateFrom='1900-01-01 00:00:00',#createdDateTo='9999-01-01 23:59:59',#updatedDateFrom='1900-01-01 00:00:00',#updatedDateTo='9999-01-01 23:59:59'
Afterwards I receive this error:
Column name or number of supplied values does not match table definition.
The order and name of columns of the table is exactly like the procedure returns.
Is there a possibility to catch only one of the tables that the procedure returns and avoid the other? I cannot change the procedure at all.
I tried declaring a table the same fields as the first select of the procedure and I get an error says that
Thank you in advance!
If all of the result sets returned are of the same structure, then you can dump them to a temp table as you are trying to do. However, that only gets you so far because if the data in the fields cannot be used to determine which result set a particular row came from, then you just have all of the result sets with no way to filter out the ones you don't want.
The only way to interact with multiple result sets individually, regardless of them having the same or differing structures, is through app code (i.e. a client connection). And if you want to do this within the context of another query, then you need to use SQLCLR.
The C# code below shows a SQLCLR stored procedure that will execute a T-SQL stored procedure that returns 4 result sets. It skips the first 2 result sets and only returns the 3rd result set. This allows the SQLCLR stored procedure to be used in an INSERT...EXEC as desired.
The code for the T-SQL stored proc that is called by the following code is shown below the C# code block. The T-SQL test proc executes sp_who2 and only return a subset of the fields being returned by that proc, showing that you don't need to return the exact same result set that you are reading; it can be manipulated in transit.
C# SQLCLR proc:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public class TheProc
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void Get3rdResultSetFromGetStuckWorkflowInstances()
{
int _ResultSetsToSkip = 2; // we want the 3rd result set
SqlConnection _Connection = null;
SqlCommand _Command = null;
SqlDataReader _Reader = null;
try
{
_Connection = new SqlConnection("Context Connection = true;");
_Command = _Connection.CreateCommand();
_Command.CommandType = CommandType.StoredProcedure;
_Command.CommandText = "tempdb.dbo.MultiResultSetTest";
// (optional) add parameters (but don't use AddWithValue!)
// The SqlDataRecord will be used to define the result set structure
// and act as a container for each row to be returned
SqlDataRecord _ResultSet = new SqlDataRecord(
new SqlMetaData[]
{
new SqlMetaData("SPID", SqlDbType.Char, 5),
new SqlMetaData("Status", SqlDbType.NVarChar, 30),
new SqlMetaData("Login", SqlDbType.NVarChar, 128),
new SqlMetaData("HostName", SqlDbType.NVarChar, 128),
new SqlMetaData("BlkBy", SqlDbType.VarChar, 5),
new SqlMetaData("DBName", SqlDbType.NVarChar, 128)
});
SqlContext.Pipe.SendResultsStart(_ResultSet); // initialize result set
_Connection.Open();
_Reader = _Command.ExecuteReader();
// Skip a predefined number of result sets
for (int _Index = 0;
_Index < _ResultSetsToSkip && _Reader.NextResult();
_Index++) ;
// Container used to move 1 full row from the result set being read
// to the one being sent, sized to the number of fields being read
Object[] _TempRow = new Object[_Reader.FieldCount];
while (_Reader.Read())
{
_Reader.GetValues(_TempRow); // read all columns
_ResultSet.SetValues(_TempRow); // set all columns
SqlContext.Pipe.SendResultsRow(_ResultSet); // send row
}
}
catch
{
throw;
}
finally
{
if(SqlContext.Pipe.IsSendingResults)
{
SqlContext.Pipe.SendResultsEnd(); // close out result set being sent
}
if(_Reader != null && !_Reader.IsClosed)
{
_Reader.Dispose();
}
_Command.Dispose();
if (_Connection != null && _Connection.State != ConnectionState.Closed)
{
_Connection.Dispose();
}
}
return;
}
}
T-SQL test proc:
USE [tempdb]
SET ANSI_NULLS ON;
IF (OBJECT_ID('dbo.MultiResultSetTest') IS NOT NULL)
BEGIN
DROP PROCEDURE dbo.MultiResultSetTest;
END;
GO
CREATE PROCEDURE dbo.MultiResultSetTest
AS
SET NOCOUNT ON;
SELECT 1 AS [ResultSet], 'asa' AS [test];
SELECT 2 AS [ResultSet], NEWID() AS [SomeGUID], GETDATE() AS [RightNow];
EXEC sp_who2;
SELECT 4 AS [ResultSet], CONVERT(MONEY, 131.12) AS [CashYo];
GO
EXEC tempdb.dbo.MultiResultSetTest;
To do:
Adjust _ResultSetsToSkip as appropriate. If you only want the first result set, simply remove both _ResultSetsToSkip and the for loop.
Define _ResultSet as appropriate
Set _Command.CommandText to be "spDebuggerViews_GetStuckWorkflowInstances"
Create the necessary parameters via SqlParameter (i.e. #workflowSpaceId='00000000-0000-0000-0000-000000000000',#pageNum=1,#pageSize=100000,#orderByColumn=N'fldid',#sortOrder=1,#workflowInstanceId=0,#stuckInstanceType=1,#createdDateFrom='1900-01-01 00:00:00',#createdDateTo='9999-01-01 23:59:59',#updatedDateFrom='1900-01-01 00:00:00',#updatedDateTo='9999-01-01 23:59:59')
If needed, add input parameters to the SQLCLR proc so that they can be used to set the values of certain SqlParameters
Then use as follows:
INSERT INTO #stalledp
(RowNumber,fldid,fldLastUpdated,fldCreationDate,fldName,fldPending)
EXEC Get3rdResultSetFromGetStuckWorkflowInstances;
There is a way to get the first record set but the others, I'm afraid, you're out of luck.
EXEC sp_addlinkedserver #server = 'LOCALSERVER', #srvproduct = '',
#provider = 'SQLOLEDB', #datasrc = ##servername
SELECT * FROM OPENQUERY(LOCALSERVER, 'EXEC testproc2')
EDIT: If you only need to check the other result set for columns to be not null you could predefine the expected results sets like so:
EXEC testproc2 WITH RESULT SETS (
(a VARCHAR(MAX) NOT NULL, b VARCHAR(MAX) NOT NULL),
(a VARCHAR(MAX) NOT NULL)
);
If the query within the stored procedure returns null values a exception is raised at that point in procedure. This will only work on sql server 2012 and upwards though.
I am trying to create a Sqlite3 database with luasql. After I require luasql.sqlite3, how do I create the database on a file?
Also, I can't seem to find the manual for luasql. Is it available anywhere?
SQLLite will create the db automatically if it does not exist.
Here is a set of Sample functions for using it in Lua (ignore the fh functions they are just internal to the program I use).
require 'luasql.sqlite3'
function opendb(dbname)
-- Check for Settings Database and create if needed
local db = fhGetPluginDataFileName()
local dbenv = assert (luasql.sqlite3())
-- connect to data source, if the file does not exist it will be created
dbcon = assert (dbenv:connect(db))
-- check table for page list
checkTable(dbcon,'pagelist',
[[CREATE TABLE pagelist(filename varchar(500), md5hash varchar(32),UNIQUE (filename))
]])
-- create table for settings
checkTable(dbcon,'settings',
[[CREATE TABLE settings(key varchar(20), directory varchar(500),
host varchar(500), folder varchar(50), userid varchar(50), password varchar(50), UNIQUE (key))
]])
return dbenv,dbcon
end
function checkTable(dbcon,table,createString)
local sql = string.format([[SELECT count(name) as count FROM sqlite_master WHERE type='table' AND name='%s']],table)
local cur = assert(dbcon:execute(sql))
local rowcount = cur:fetch (row, "a")
cur:close()
if tonumber(rowcount) == 0 then
-- Table not found create it
res,err = assert(dbcon:execute(createString))
end
end
function closedb(dbenv,dbcon)
dbcon:close()
dbenv:close()
end
function loadSettings(dbcon)
local sql = [[SELECT * FROM settings]]
local cur,err = assert(dbcon:execute(sql))
local row = cur:fetch({},'a')
cur:close()
if row then
return row
else
-- return default values
return {
directory = fhGetContextInfo('CI_PROJECT_PUBLIC_FOLDER')..'\\FH Website',
host = 'websitehost',
folder = '/',
userid = 'user',
password = 'password',
new = 'yes'
}
end
end
function saveSettings(dbcon,settings)
-- Check for Settings
if settings.new == 'yes' then
-- Create
sql = string.format([[insert into settings (directory, host, folder, userid, password) Values('%s','%s','%s','%s','%s')]],settings.directory,settings.host,settings.folder,settings.userid,settings.password)
else
-- Update
sql = string.format([[update settings set directory = '%s', host = '%s',folder = '%s',userid = '%s', password = '%s']],settings.directory,settings.host,settings.folder,settings.userid,settings.password)
end
local res = assert(dbcon:execute(sql))
end