SELECT sp_WhoIsActive into Table - sql-server

I'm trying to script sp_WhoIsActive into a table. The goal is feed the table with an Agent Job every 10 seconds.
I followed this guide and I tried to feed the table this way:
--Log activity into table.
DECLARE #destination_table VARCHAR(4000) =
'[Monitoring].[dbo].[WhoIsActive] '
EXEC sp_WhoIsActive
#get_plans = 1,
#get_transaction_info = 1,
#destination_table = #destination_table;
But as result I receive the error:
Warning: The join order has been enforced because a local join hint is used.
Msg 50000, Level 16, State 1, Procedure sp_WhoIsActive, Line 1111 [Batch Start Line 0]
Destination table not properly formatted.
On Google I found many guides talking about a solution that could help me execute a Stored Procedure into a temp table and from there I could create a table:
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;',
'EXEC sp_WhoIsActive')
SELECT * FROM #MyTempTable
But this process too is failing with error:
Msg 11526, Level 16, State 1, Procedure sys.sp_describe_first_result_set, Line 1 [Batch Start Line 12]
The metadata could not be determined because statement 'INSERT #sessions
(
recursion,
session_id,
request_id' in procedure 'sp_WhoIsActive' uses a temp table.
I tried following Kendra Little blog but that too is not working.
In the end I scripted out the table manually:
CREATE TABLE [dbo].[WhoIsActive](
[dd_hh_mm_ss_mss] [nvarchar](50) NOT NULL,
[session_id] [tinyint] NOT NULL,
[sql_text] [nvarchar](max) NOT NULL,
[sql_command] [nvarchar](400) NOT NULL,
[login_name] [nvarchar](50) NOT NULL,
[wait_info] [nvarchar](50) NOT NULL,
[tran_log_writes] [nvarchar](50) NOT NULL,
[CPU] [smallint] NOT NULL,
[tempdb_allocations] [smallint] NOT NULL,
[tempdb_current] [smallint] NOT NULL,
[blocking_session_id] [nvarchar](50) NOT NULL,
[reads] [int] NOT NULL,
[writes] [float] NOT NULL,
[physical_reads] [tinyint] NOT NULL,
[query_plan] [nvarchar](50) NOT NULL,
[used_memory] [tinyint] NOT NULL,
[status] [nvarchar](50) NOT NULL,
[tran_start_time] [datetime2](7) NOT NULL,
[implicit_tran] [nvarchar](50) NOT NULL,
[open_tran_count] [tinyint] NOT NULL,
[percent_complete] [nvarchar](50) NOT NULL,
[host_name] [nvarchar](50) NOT NULL,
[database_name] [nvarchar](50) NOT NULL,
[program_name] [nvarchar](100) NOT NULL,
[start_time] [datetime2](7) NOT NULL,
[login_tine] [datetime2](7) NOT NULL,
[request_id] [tinyint] NOT NULL,
[collection_time] [datetime2](7) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
But that too is failing and I cannot feed the table with a job.
sp_WhoIsActive is so popular, I cannot believe I'm the only one trying to insert the results into a table.

You need to create a table suitable to use with the output of the procedure, the schema of which can vary depending on the options you use.
SP_WhoIsActive will actually give you the create script, so to capture the default options just do
declare #definition varchar(max)
exec sp_WhoIsActive #return_schema = 1, #schema = #definition output
print #definition
This returns the appropriate T-SQL:
CREATE TABLE < table_name > (
[dd hh:mm:ss.mss] VARCHAR(8000) NULL
,[session_id] SMALLINT NOT NULL
,[sql_text] XML NULL
,[login_name] NVARCHAR(128) NOT NULL
,[wait_info] NVARCHAR(4000) NULL
,[CPU] VARCHAR(30) NULL
,[tempdb_allocations] VARCHAR(30) NULL
,[tempdb_current] VARCHAR(30) NULL
,[blocking_session_id] SMALLINT NULL
,[reads] VARCHAR(30) NULL
,[writes] VARCHAR(30) NULL
,[physical_reads] VARCHAR(30) NULL
,[used_memory] VARCHAR(30) NULL
,[status] VARCHAR(30) NOT NULL
,[open_tran_count] VARCHAR(30) NULL
,[percent_complete] VARCHAR(30) NULL
,[host_name] NVARCHAR(128) NULL
,[database_name] NVARCHAR(128) NULL
,[program_name] NVARCHAR(128) NULL
,[start_time] DATETIME NOT NULL
,[login_time] DATETIME NULL
,[request_id] INT NULL
,[collection_time] DATETIME NOT NULL
)
Edit and run with the required target table name, then you can run sp_whoisactive with the destination table option
exec sp_WhoIsActive #destination_table='Monitoring.dbo.WhoIsActive'
See the docs

Related

Executing a stored procedure by picking SQL variable from a list in T-SQL without using Cursor

I have a list of values, and i need the variable to pick it up one by one and execute the commands below. I need to achieve something like below in T-SQL. Is it possible without cursors?
SET NOCOUNT ON;
DECLARE #IPA VARCHAR(10)
FOR #IPA IN ['ADV, 'AC','AHA','ALPEB','AG','APCWEB]
IF OBJECT_ID('[ESProcess].[dbo].[EJ_Test]') IS NOT NULL
DROP TABLE [ESProcess].[dbo].[EJ_Test]
CREATE TABLE [ESProcess].[dbo].[EJ_Test]
(
[PRIM] [varchar](50) NULL,
[CLAIM_ID] [varchar](100) NULL,
[P_CLAIMNO] [varchar](100) NULL,
[Pro] [varchar](3) NULL,
[VALUE] [varchar](50) NULL,
[ErrorCode] [int] NULL,
[DESCRIP] [varchar](500) NULL,
[FILENAME] [varchar](300) NULL
)
INSERT INTO [ESProcess].[dbo].[EJ_Test]
SELECT
PRIM,a.CLAIM_ID,P_CLAIMNO, Pro, u.VALUE,
NULL AS ErrorCode, NULL AS DESCRIP, [FILENAME]
FROM
[SPID].[#IPA].[dbo].837_in_1 a
JOIN
[SPID].[#IPA].[dbo].[837_In_U] u ON a.ED_ID = u.M_ID
WHERE
a.CREATEDATE >= '20221001'
AND u.FNO = '20'
AND Pro = 'D'
END
Here. Note that drop-creating the table means that at the end you will only have data from APCWEB.
SET NOCOUNT ON;
DECLARE #IPA VARCHAR(10)
declare #sql nvarchar(max)
create table #ipas
(
ord int
,ipa varchar(10)
)
insert #ipas(ord,ipa) values
(1,'ADV')
,(2,'AC')
,(3,'AHA')
,(4,'ALPEB')
,(5,'AG')
,(6,'APCWEB')
declare ipa_cursor cursor local fast_forward for
select ipa from #ipas order by ord
open ipa_cursor
while 1=1
begin
fetch next from ipa_cursor into #IPA
if ##fetch_status<>0 break
set #sql=N''+
'IF OBJECT_ID(''[ESProcess].[dbo].[EJ_Test]'') IS NOT NULL
DROP TABLE [ESProcess].[dbo].[EJ_Test]
CREATE TABLE [ESProcess].[dbo].[EJ_Test]
(
[PRIM] [varchar](50) NULL,
[CLAIM_ID] [varchar](100) NULL,
[P_CLAIMNO] [varchar](100) NULL,
[Pro] [varchar](3) NULL,
[VALUE] [varchar](50) NULL,
[ErrorCode] [int] NULL,
[DESCRIP] [varchar](500) NULL,
[FILENAME] [varchar](300) NULL
)
INSERT INTO [ESProcess].[dbo].[EJ_Test]
SELECT
PRIM,a.CLAIM_ID,P_CLAIMNO, Pro, u.VALUE,
NULL AS ErrorCode, NULL AS DESCRIP, [FILENAME]
FROM
[SPID].'+quotename(#IPA)+'.[dbo].837_in_1 a
JOIN
[SPID].'+quotename(#IPA)+'.[dbo].[837_In_U] u ON a.ED_ID = u.M_ID
WHERE
a.CREATEDATE >= ''20221001''
AND u.FNO = ''20''
AND Pro = ''D'''
exec sp_executesql #sql
end -- cursor while
close ipa_cursor
deallocate ipa_cursor

Dynamically insert into table using sp_executesql in SQL Server

I got error
Msg 207, Level 16, State 1, Line 33
Invalid column name 'Front Brakes1'
when executing a stored procedure which looks like this:
DECLARE #SqlStatement NVARCHAR(MAX);
SET #SqlStatement = 'INSERT INTO [SalesLT].[Product]('+ #Column+ ') VALUES('+#Value+')';
PRINT #SqlStatement
EXEC sys.sp_executesql #SqlStatement, N'#Column NVARCHAR(MAX), #Value NVARCHAR(MAX)',#Column,#Value
PRINT #SqlStatement results in:
INSERT INTO [SalesLT].[Product](Name, ProductNumber, Color, StandardCost, ListPrice, Weight)
VALUES ("Front Brakes1", "FB-98731", "Silver1", 47.286, 106.5, 317)
Additionally, here is the table design I wanna insert data into:
CREATE TABLE [SalesLT].[Product]
(
[ProductID] [INT] IDENTITY(1,1) NOT NULL,
[Name] [dbo].[Name] NOT NULL,
[ProductNumber] [NVARCHAR](25) NOT NULL,
[Color] [NVARCHAR](15) NULL,
[StandardCost] [MONEY] NOT NULL,
[ListPrice] [MONEY] NOT NULL,
[Size] [NVARCHAR](5) NULL,
[Weight] [DECIMAL](8, 2) NULL,
[ProductCategoryID] [INT] NULL,
[ProductModelID] [INT] NULL,
[SellStartDate] [DATETIME] NOT NULL,
[SellEndDate] [DATETIME] NULL,
[DiscontinuedDate] [DATETIME] NULL,
[ThumbNailPhoto] [VARBINARY](MAX) NULL,
[ThumbnailPhotoFileName] [NVARCHAR](50) NULL,
[rowguid] [UNIQUEIDENTIFIER] ROWGUIDCOL NOT NULL,
[ModifiedDate] [DATETIME] NOT NULL,
)
Enclose the T-SQL string literals in single quotes instead of double-quotes so that the resultant SQL statement is:
INSERT INTO [SalesLT].[Product](Name,ProductNumber,Color,StandardCost,ListPrice,Weight)
VALUES('Front Brakes1','FB-98731','Silver1',47.286,106.5,317);
Double-quotes (or square brackets) denote identifiers, such as table and column names.

SQL Server Always Encrypted Operand type clash: varchar is incompatible with varchar(60) when running EXEC sproc

I am unable to EXEC a stored procedure that upserts a table that has an encrypted column using Always Encrypted. However, I am able to copy the SQL from the sproc and run that as regular SQL with the parameters set, Just cannot get the sproc to fire when executing the sproc via the EXEC function in SSMS which is also causing problems in the application
The table has a trigger on it that inserts into another audit table of similar structure that is also encrypted using the same encryption. I have done the usual thing:
Checking the Enable Parameterizaion for Always Encrypted in Query Options Setting column encryption setting=enabled on the Connection Settings.
Refreshing the encyrption metadata for the sproc:
EXEC sp_refresh_parameter_encryption 'organization.uspOrganizationAddressUpsert'
Tables:
CREATE TABLE [organization].[OrganizationAddress](
[OrganizationAddressId] [int] IDENTITY(1,1) NOT NULL,
[CreatedUser] [int] NOT NULL,
[CreatedDate] [datetime2](7) NOT NULL,
[LastUpdateUser] [int] NOT NULL,
[LastUpdateDate] [datetime2](7) NOT NULL,
[RemovedDate] [datetime2](7) NULL,
[Address1] [varchar](60) NOT NULL,
[Address2] [varchar](60) NULL,
[City] [varchar](60) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_Auto1], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL,
[State] [varchar](60) NOT NULL,
[ZipCode] [varchar](60) NOT NULL,
[ClientNumberId] [int] NOT NULL
CREATE TABLE [audit].[OrganizationAddressAudit](
[OrganizationAddressId] [int] NOT NULL,
[CreatedUser] [int] NOT NULL,
[CreatedDate] [datetime2](7) NOT NULL,
[LastUpdateUser] [int] NOT NULL,
[LastUpdateDate] [datetime2](7) NOT NULL,
[RemovedDate] [datetime2](7) NULL,
[Address1] [varchar](60) NOT NULL,
[Address2] [varchar](60) NULL,
[City] [varchar](60) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_Auto1], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL,
[State] [varchar](60) NOT NULL,
[ZipCode] [varchar](60) NOT NULL,
[ClientNumberId] [int] NOT NULL,
[OperationDate] [datetime] NOT NULL,
[Operation] [varchar](50) NOT NULL,
[OperationBy] [varchar](100) NOT NULL
Stored Procedure:
ALTER PROCEDURE [organization].[uspOrganizationAddressUpsert]
#OrganizationId INT,
#ExecutingUserId INT,
#Address1 VARCHAR(60),
#Address2 VARCHAR(60),
#City VARCHAR(60),
#State VARCHAR(60),
#ZipCode VARCHAR(60),
#ClientNumberId INT
AS
BEGIN
SET NOCOUNT ON
DECLARE #RightNow AS DATETIME2 = SYSDATETIME()
If EXISTS (Select 1 From [organization].[OrganizationAddress] Where ClientNumberId = #ClientNumberId)
BEGIN
UPDATE [organization].[OrganizationAddress] SET
LastUpdateUser = #ExecutingUserId,
LastUpdateDate = #RightNow,
Address1 = #Address1,
Address2 = #Address2,
City = #City,
[State] = #State,
ZipCode = #ZipCode,
RemovedDate = Null
Where ClientNumberId = #ClientNumberId
END
ELSE
BEGIN -- INSERT part of the UPSERT
INSERT INTO [organization].[OrganizationAddress]
(CreatedUser
,CreatedDate
,LastUpdateUser
,LastUpdateDate
,Address1
,Address2
,City
,[State]
,ZipCode
,ClientNumberId)
VALUES
(#ExecutingUserId
,#RightNow
,#ExecutingUserId
,#RightNow
,#Address1
,#Address2
,#City
,#State
,#ZipCode
,#ClientNumberId)
END
END
Running the stored procedure code with the paramteers set is fine, but I am unable to EXEC the sproc:
declare #orgId INT = 1;
declare #client int = 888;
declare #user int = 1;
declare #Add1 varchar(60)= 'Test Address1';
declare #Add2 varchar(60)= 'Test Address2';
declare #city varchar(60) = 'City';
declare #state varchar(60) = 'St';
declare #zip varchar(60) = '12345';
EXEC organization.uspOrganizationAddressUpsert
#OrganizationID=#orgID,
#ExecutingUserId = #user, -- int
#Address1 = #Add1, -- varchar(60)
#Address2 = #Add2, -- varchar(60)
#City = #city, -- varchar(60)
#State = #state, -- varchar(60)
#ZipCode = #zip, -- varchar(60)
#ClientNumberId = #client; -- int
Msg 206, Level 16, State 2, Procedure uspOrganizationAddressUpsert, Line 0 [Batch Start Line 1]
Operand type clash: varchar is incompatible with varchar(60) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'BankruptcyApp') collation_name = 'SQL_Latin1_General_CP1_CI_AS'
I created a similar table in a test DB with VARCHAR(60) for the enrcrypted columns, a trigger, and an audit table and its working fine there and I cant find any differences in the table/sproc/trigger that would allow it to work there and not here. I've pretty much exhausted the other posts and blogs I can find.
Fixed! Needed to update the app code to specify the data type and length:
parameters.Add("#City", organizationAddress.City, System.Data.DbType.AnsiString, System.Data.ParameterDirection.Input, 60);
where it was previously just:
parameters.Add("#City", organizationAddress.City)
This at least get the app to run the sproc but still cant run it from SSMS via EXEC

SQL Trigger - How to update a table whenever another table in another database is being updated?

So I have a table called "persons" in a database test1:
CREATE TABLE [dbo].[persons](
[ID] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](50) NULL,
[FirstName] [varchar](50) NULL,
[Job] [varchar](50) NULL,
[Extension] [char](10) NULL,
[EMail] [varchar](50) NULL,
[Dept] [int] NULL,
[MobileNumber] [char](10) NULL,
[District] [int] NULL,
[Status] [varchar](50) NULL,
[InOutStatus] [varchar](5) NULL,
[InOutDescr] [varchar](50) NULL,
[InOutDirections] [varchar](255) NULL,
[InOutReturn] [varchar](50) NULL,
[login] [varchar](50) NULL,
[StatusExpiry] [datetime] NULL
) ON [PRIMARY]
And a table called "Users" in a database test2:
CREATE TABLE [dbo].[Users](
[User_ID] [int] NOT NULL,
[Firstname] [nvarchar](50) NULL,
[Lastname] [nvarchar](50) NULL,
[Username] [nvarchar](50) NULL,
[Status] [nvarchar](50) NULL
) ON [PRIMARY]
What I'm trying to do is create a Trigger where if the FirstName, LastName, login, and/or Status column in the persons table is updated, then the same value is updated in its identical column in the Users table. This is a Trigger I came up with but it doesn't work:
ALTER TRIGGER [dbo].[UserUpdteTrig]
ON [dbo].[persons]
AFTER UPDATE
AS
BEGIN
DECLARE #uid int;
DECLARE #fname nvarchar(50);
DECLARE #lname nvarchar(50);
DECLARE #uname nvarchar(50);
DECLARE #stat nvarchar(50);
SELECT #fname = i.FirstName, #lname = i.LastName, #uname = i.login, #stat = i.Status
FROM inserted i
UPDATE [test2].[dbo].[Users]
SET Firstname = #fname , Lastname = #lname, Username = #uname, Status = #stat
FROM [test2].[dbo].[Users] u INNER JOIN inserted i ON u.User_ID = i.ID
END
I keep getting an error that says: The row value updated and deleted either do not make the row unique or they alter multiple rows, which the PK in both tables are all unique and the PK shouldn't be altered anyway.
You dont need any variables at all just a simple update should be enough.
ALTER TRIGGER [dbo].[UserUpdteTrig]
ON [dbo].[persons]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE u
SET u.Firstname = i.FirstName
, u.Lastname = i.Lastname
, u.Username = i.Username
, u.[Status] = i.[Status]
FROM [test2].[dbo].[Users] u
INNER JOIN inserted i ON u.[User_ID] = i.ID
END

T-SQL insert trigger

The database I am working on has the following insert trigger. The problem is the trigger will not work with a multi-row insert. When I try and insert more than one row at a time I get the following message.
Msg 512, Level 16, State 1, Procedure _ti_UD06, Line 8
Subquery returned more than 1 value. This is not permitted when the subquery
follows =, !=, <, <= , >, >= or when the subquery is used as an
expression. I think the problem is with the following statement it
will return more than one value when multiple rows are inserted.
How can I make this insert trigger work with multiple rows?
IF(SELECT PROGRESS_RECID FROM inserted) IS NULL
There are 2 columns in the table, PROGRESS_RECID and PROGRESS_RECID_IDENT_.
I think the PROGRESS_RECID_IDENT_ is an Identity column for SQL Server. The PROGRESS_RECID_INDENT is used by the PROGRESS Server.
If a new record is inserted the trigger checks to see if the PROGRESS_RECID is null and will set it to the inserted.Identity
ALTER trigger [dbo].[_ti_UD06] ON [dbo].[UD06] for insert as
begin
if ( select PROGRESS_RECID from inserted) is NULL
begin
update t set PROGRESS_RECID = i.IDENTITYCOL
from UD06 t JOIN INSERTED i ON
t.PROGRESS_RECID_IDENT_ = i.PROGRESS_RECID_IDENT_
select convert (bigint, ##identity)
end
end
Here is the Table definition
CREATE TABLE [dbo].[UD06](
[Company] [nvarchar](8) NULL,
[Key1] [nvarchar](50) NOT NULL,
[Key2] [nvarchar](50) NULL,
[Key3] [nvarchar](50) NULL,
[Key5] [nvarchar](50) NULL,
[Character01] [nvarchar](max) NULL,
[Character02] [nvarchar](max) NULL,
[Character03] [nvarchar](max) NULL,
[Character04] [nvarchar](max) NULL,
[Character05] [nvarchar](max) NULL,
[Character06] [nvarchar](max) NULL,
[Character07] [nvarchar](max) NULL,
[Character08] [nvarchar](max) NULL,
[Character09] [nvarchar](max) NULL,
[Character10] [nvarchar](max) NULL,
[SysRowID] [nvarchar](36) NULL,
[SysRevID] [int] NULL,
[BitFlag] [int] NULL,
[GlobalUD06] [tinyint] NULL,
[GlobalLock] [tinyint] NULL,
[PROGRESS_RECID] [bigint] NULL,
[PROGRESS_RECID_IDENT_] [bigint] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
I think you're pretty close already:
ALTER trigger [dbo].[_ti_UD06] ON [dbo].[UD06] for insert as
begin
UPDATE t
SET PROGRESS_RECID = t.PROGRESS_RECID_IDENT_ --not "IDENTITYCOL"
FROM UD06 t
JOIN inserted i ON t.PROGRESS_RECID_IDENT_ = i.PROGRESS_RECID_IDENT_
WHERE i.PROGRESS_RECID is Null
-- Not sure what this bit is for? I doubt it's a good idea though...
select convert (bigint, ##identity)
end

Resources