I am working in a SQL Server environment with one master server and many target servers. It sometimes happens that for a reason or another one a target server may go out of sync.
I have the choice when that occurs to manually run the following stored procedure to re-sync the target server:
exec sp_resync_targetserver #server_name = 'RMAPP11DV1\PROJECT'
My assignment is to automate the process so that we do not have to manually run it. I should write a script and schedule it as a job that should run a a schedule time to selectively find and re-sync only the target servers that are currently out of sync.
This is my approach so far. It is not working as expected (can not do the re-sync when ran), that is why I need any one output. Thanks in advance:
use msdb
set nocount on;
if exists (select * from tempdb.sys.all_objects where name like '%#targetstatus%') --deleting the table if it already exists
drop table #targetstatus
create table #targetstatus
(
server_id int not null,
server_name nvarchar(300) not null,
location nvarchar(350) null,
time_zone_adjustment int not null,
enlist_date datetime not null,
last_poll_date datetime not null,
status int not null,
unread_instructions int not null,
local_time datetime not null,
enlisted_by_nt_user nvarchar(100) not null,
poll_interval int not null
)
insert into #targetstatus
exec sp_help_targetserver
select * from #targetstatus
if exists (select * from tempdb.sys.all_objects where name like '%#needresync%') --deleting the table if it already exists
drop table #needresync
create table #needresync -- will hold the target servers needing to be re-synced
(
server_id int not null,
server_name nvarchar(300) not null,
location nvarchar(350) null,
time_zone_adjustment int not null,
enlist_date datetime not null,
last_poll_date datetime not null,
status int not null,
unread_instructions int not null,
local_time datetime not null,
enlisted_by_nt_user nvarchar(100) not null,
poll_interval int not null
)
insert into #needresync
select *
from #targetstatus
where status <> 1 -- we only want to run the syncing proc on the target with a status diff of #1
select * from #needresync
declare #target_server varchar(100);
set #target_server = ' '
while #target_server <> ' '
begin
set #target_server = (select max(server_name) from #needresync);
exec msdb.dbo.sp_resync_targetserver #server_name = '#target_server';
-- #target_server = #target_server + 1
end
You are not deleting the row out of #needresync. You must delete each row one by one inside the while loop.
However, a much easier method exists. You can use the systargetservers DMV without using any temp tables at all:
DECLARE #server sysname =
(SELECT TOP 1 FROM dbo.systargetservers WHERE status = 2); -- 2 = Re-sync Pending
WHILE (#server IS NOT NULL)
BEGIN
EXEC sp_resync_targetserver #server;
SET #server =
(SELECT TOP 1 FROM dbo.systargetservers WHERE status = 2);
END;
Related
Take the following script:
EXEC sp_MSforeachtable #command1 = "DROP TABLE ?";
GO
CREATE TABLE _adminServices (
[ServiceID] INT CHECK ([ServiceID] > 0) NOT NULL IDENTITY,
[ServiceName] NVARCHAR(255) DEFAULT NULL,
[ManagerStaffID] INT CHECK ([ManagerStaffID] > 0) DEFAULT NULL,
[ODMStaffID] INT CHECK ([ODMStaffID] > 0) DEFAULT NULL,
[ReferralInactivityDays] INT DEFAULT NULL,
[TargetSupportHours] INT DEFAULT NULL,
[ShowInLists] SMALLINT NOT NULL DEFAULT '1',
[RecordEntryDate] DATETIME2(0) DEFAULT NULL,
[RecordModDate] DATETIME2(0) DEFAULT NULL,
PRIMARY KEY ([ServiceID])
) ;
CREATE INDEX [ManagerStaffID] ON _adminServices ([ManagerStaffID]);
CREATE INDEX [ODMStaffID] ON _adminServices ([ODMStaffID]);
CREATE INDEX [ShowInLists] ON _adminServices ([ShowInLists]);
GO
EXEC sp_MSforeachtable #command1 = 'IF (
select COUNT(TABLE_NAME)
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+''.''+TABLE_NAME), COLUMN_NAME, ''IsIdentity'') = 1
AND TABLE_SCHEMA+''.''+TABLE_NAME = ''?''
) = 1
BEGIN
SET IDENTITY_INSERT ? ON;
END;';
GO
INSERT INTO _adminServices (ServiceID, ServiceName, ManagerStaffID, ODMStaffID, ReferralInactivityDays, TargetSupportHours, ShowInLists, RecordEntryDate, RecordModDate) VALUES
(1, 'Service 1', 16, 18, 0, NULL, 1, '2017-07-21 11:59:56', '2017-10-25 09:38:02');
GO
When I execute the aforementioned script in SSMS I get the following error:
Msg 544, Level 16, State 1, Line 36
Cannot insert explicit value for identity column in table '_adminServices' when IDENTITY_INSERT is set to OFF.
Can anyone tell me why?
EDIT: My goal is the following: I have multiple tables and multiple inserts.
For the Inserts I have the scripts. Since I don't want to write the SET IDENTITY_INSERT ON and OFF for every table since I just have the INSERT INTO queries on a file, I want a way to do the following:
Delete all the tables in the DB
Create all the tables (I have the SQL for this)
Set all the required identities to ON
Run the Inserts (I have the SQL for this)
Set all the required identities to OFF
sp_MSforeachtable run on another session in relation to your insert
At any time, only one table in a session can have the IDENTITY_INSERT property set to ON.
General scheme of inserting the original value:
CREATE TABLE
SET IDENTITY INSERT ON
INSERT VALUES
SET IDENTITY INSERT OFF
If you table not have single structure sp_MSforeachtable you will not be suitable
I am new to SQL Server and T-SQL, but I do have some experience building applications in MS Access.
This stored procedure runs fine when I execute it from the application, however when I am debugging it in SSMS, I get an error
Unable to Step. Invalid Operation.
but it will allow me to step through. Based on my research, it seems like I am creating a race condition but I have not been able to correctly fix the issue. I would also appreciate any advice to optimize this or fix any issues that are apparent.
What the code does:
This code is to enter a new customer into the database. The first select statement looks for an existing ID. If the ID is null, it will add a new customer. If the ID is not null, it will not add the customer. The same goes for the second IF statement to check if #pName2 and #pName3 are null before inserting these values.
Here is my code:
#pUID nvarchar(16) = null,
#pName1 nvarchar(50) = null,
#pName2 nvarchar(50) = null,
#pName3 nvarchar(50) = null,
#pAddress1 nvarchar(30) = null,
#pAddress2 nvarchar(30) = null,
#pAddress3 nvarchar(30) = null,
#pZipCode nvarchar(30) = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ID INT
SELECT #ID = ID FROM tblCustomer WHERE strUID = #pUID
IF #ID IS NULL
BEGIN
DECLARE #Customer_ID INT
INSERT INTO tblCustomer(strUID, strName)
VALUES(#pUID, #pName1)
SET #Customer_ID = ##IDENTITY
IF (#pName2 <> '') OR (#pName3 <> '')
BEGIN
INSERT INTO tblSecondaryCustomer(CustomerID, strName2, strName3)
VALUES(#Customer_ID, #pName2, #pName3)
END
INSERT INTO tblAddress(CustomerID, strAddress1, strAddress2, strAddress3, strZipCode)
VALUES(#Customer_ID, #pAddress1, #pAddress2, #pAddress3, #pZipCode)
END
END
Try replacing your IF statement with the following:
IF NOT EXISTS(SELECT ID FROM tblCustomer WHERE strUID = #pUID)
It doesn't seem your using #ID other than a check for existence...and you can use the ISNULL function to make sure you cover NULL cases...
IF (ISNULL(#pName2,'') <> '') OR (ISNULL(#pName3,'') <> '')
HTH
Dave
My insert procedure is working fine the way i want. But update is not working with scope identity.
SET ANSI_NULLS ON
ALTER PROCEDURE [dbo].[spr_unitCreation]
(
#Unit_Name VARCHAR(50) = NULL,
#Unit_Abbreviation VARCHAR(50) = NULL,
#Unit_type VARCHAR(50) = NULL,
#Decimal_Places VARCHAR(50) = NULL,
#Description VARCHAR(50) = NULL,
#Super_Unit VARCHAR(50) = NULL,
#Per_Unit VARCHAR(50) = NULL,
#unit_Id INT OUTPUT,
#abc VARCHAR(50) = NULL
)
AS
BEGIN
IF #abc = 'update' BEGIN
SET NOCOUNT ON;
SELECT #unit_Id AS SCOPE_IDENTITY
UPDATE tbl_UnitCreation
SET Unit_Name = #Unit_Name,
Unit_Abbreviation = #Unit_Abbreviation,
Unit_type = #Unit_type,
Decimal_Places = #Decimal_Places,
Description = #Description,
Super_Unit = #Super_Unit,
Per_Unit = #Per_Unit
WHERE unit_Id = #unit_Id
END
END
SELECT * FROM tbl_UnitCreation
SCOPE_IDENTITY returns the last identity value inserted into an identity column. You are not inserting a row.
To update a row all you need is to pass a value to #unit_Id when executing [spr_unitCreation]. Also remove the line "SELECT #unit_Id AS SCOPE_IDENTITY" from your code.
Based on the comments, you need to find the correct id by searching on relevant details. So you can get the id like this:
SELECT #unit_Id = unit_Id
FROM tbl_UnitCreation
WHERE Unit_Name=#Unit_Name -- NB: Ensure this column contains your relevant details
Another commonly used option is to use the OUTPUT clause of the UPDATE statement, inserting all the updated/"inserted" primary keys and Unit_name into a tablevariable.
https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-2017
How to find which query is consuming more space in temp db in SQL 2000 version. I do not want to use SQL profiler as there is not much space on disk.
Issue is its 2000 version. No information can be pulled using dmv's.
How to track that between 1-2 which query and on which database is making tempdb size to grow as much that notifications are coming that could allocate page under tempdb, it is full.
You can create a proc out of the script below which can be executed by a job. More or less this is a template and can be altered however you see fit.
EDIT: Added additional comments below.
--Create temp table for sysprocesses records
IF OBJECT_ID('tempdb.dbo.#SYSPROC') IS NOT NULL
DROP TABLE #SYSPROC;
BEGIN
CREATE TABLE #SYSPROC
(
spid smallint NOT NULL,
dbid smallint NOT NULL,
blocked smallint NOT NULL,
lastwaittype nchar(32) NOT NULL,
cpu int NOT NULL,
physical_io int NOT NULL,
memusage int NOT NULL,
login_time datetime NOT NULL,
Last_batch datetime NOT NULL,
status nchar(30) NOT NULL,
cmd nchar(16) NOT NULL,
loginame nchar(128) NOT NULL,
sql_handle binary(20) NOT NULL,
sh_text text NULL,
snapshot_dt datetime NULL
)
END;
--Insert sysprocesses records into temp #SYSPROC
INSERT INTO #SYSPROC
(
spid,
dbid,
blocked,
lastwaittype,
cpu,
physical_io,
memusage,
login_time,
Last_batch,
status,
cmd,
loginame,
sql_handle,
snapshot_dt
)
SELECT
sp.spid,
sp.dbid,
sp.blocked,
sp.lastwaittype,
sp.cpu,
sp.physical_io,
sp.memusage,
sp.login_time,
sp.Last_batch,
sp.status,
sp.cmd,
sp.loginame,
sp.sql_handle,
GETDATE()
FROM master.dbo.sysprocesses sp
WHERE sp.spid > 50;
/*
Update temp #SYSPROC with sql text. Since CROSS APPLY is not
available in SQL Server 2000, a loop is required to interate
through each record.
*/
DECLARE #min_spid smallint = (SELECT MIN(spid) FROM #SYSPROC);
DECLARE #max_spid smallint = (SELECT MAX(spid) FROM #SYSPROC);
DECLARE #sql_handle binary(20);
DECLARE #sql_text varchar(max);
WHILE #min_spid <= #max_spid
BEGIN
--Set #sql_handle variable to be evaluated by the fn_get_sql function
SELECT
#sql_handle = S.sql_handle
FROM #SYSPROC S
WHERE spid = #min_spid
--Identify the sql_text for the session by passing the #sql_handle variablet through fn_get_sql
SELECT
#sql_text = H.text
FROM fn_get_sql(#sql_handle) H
--Update #SYSPROC with the sql_text.
UPDATE S
SET sh_text = #sql_text
FROM #SYSPROC S
WHERE spid = #min_spid
SET #min_spid = #min_spid + 1
END;
INSERT INTO <SOMETABLE YOU CREATE>
(
spid,
dbid,
blocked,
lastwaittype,
cpu,
physical_io,
memusage,
login_time,
Last_batch,
status,
cmd,
loginame,
sql_handle,
snapshot_dt
)
SELECT
spid,
dbid,
blocked,
lastwaittype,
cpu,
physical_io,
memusage,
login_time,
Last_batch,
status,
cmd,
loginame,
sql_handle,
snapshot_dt
FROM #SYSPROC
Hope this helps!
I'm trying to debug\execute a SP from t-sql (sql server 2008) and when I execute the following sql it returns only a message 'Command(s) completed successfully'.
I know the SP is returning the data in a table via the #RETURN_VALUE parameter, how do I get this to display in sql query window.
exec STARMS.dbo.GetMetaData ##Assembly=13366,##Namespace=NULL,##ParameterName=NULL,##Standard=0,##Timestamp=NULL
The SP looks something like this ( removed the main body) the interesting part is the creation of the temp table and then returning the contents of the temp table:
CREATE PROCEDURE [dbo].[GetMetaData]
##Assembly Sql_Variant = NULL,
##Namespace Varchar(30) = NULL,
##ParameterName Varchar(40) = NULL,
##Standard Bit = 0,
##Timestamp DateTime = NULL
AS
SET NOCOUNT ON
DECLARE #ResultTable TABLE (AssemblyId Int, Namespace Varchar(30), ParameterName Varchar(40), Value Varchar(100))
-- Does loads of stuff and then inserts into #ResultTable table...
SET NOCOUNT OFF
-- Return the result
SELECT AssemblyId, Namespace, ParameterName, [Value]
FROM #ResultTable
RETURN
Note: the reason I'm asking the question is because I'm trying to look at the performance of the SP in SQL Server 2008 and I'm unsure why this doesn't return the data in the query window.
Check your full code of SP, may be somewhere there is a RETURN statement, so - the SP will not return any data (pay attention on IF SomeContition IS TRUE RETURN):
CREATE PROCEDURE [dbo].[GetMetaData]
##Assembly Sql_Variant = NULL,
##Namespace Varchar(30) = NULL,
##ParameterName Varchar(40) = NULL,
##Standard Bit = 0,
##Timestamp DateTime = NULL
AS
SET NOCOUNT ON
DECLARE #ResultTable TABLE (AssemblyId Int, Namespace Varchar(30), ParameterName Varchar(40), Value Varchar(100))
-- Does loads of stuff and then inserts into #ResultTable table...
IF SomeContition IS TRUE RETURN
SET NOCOUNT OFF
-- Return the result
SELECT AssemblyId, Namespace, ParameterName, [Value]
FROM #ResultTable
RETURN