How can I delete a maintenance plan with T SQL? - sql-server

I have 87 servers that each have maintenance plans that need to be deleted to be replaced with agent jobs. Here's what I've tried:
DECLARE #planId UNIQUEIDENTIFIER;
select #planId = p.id
from msdb..sysmaintplan_plans p
where p.name LIKE 'Night%';
PRINT #planId;
EXEC msdb..sp_delete_maintenance_plan #planId;
and the result that I get:
E0BC518C-CFD4-4BB0-A843-74B61B22B72E
Msg 14262, Level 16, State 1, Procedure sp_delete_maintenance_plan,
Line 12 [Batch Start Line 3] The specified #plan_id
('E0BC518C-CFD4-4BB0-A843-74B61B22B72E') does not exist.
How can I get this to work? Would a powershell script work better?

Besides sp_delete_job, you may also want to have a look at sp_ssis_deletepackage, but this one is not documented. Try using Profiler to see what is called when you delete a maintenance plan.

I have solved this issue by this:
declare #folder_id uniqueidentifier
declare #plan_id uniqueidentifier
declare #plan_name nvarchar (100) = 'Plan Name'
select #plan_id = id from msdb.dbo.sysmaintplan_plans where [name] = #plan_name
select #folder_id = folderid from msdb.dbo.sysssispackages where name = #plan_name
exec msdb.[dbo].sp_ssis_deletepackage #plan_name,#folder_id
exec msdb.[dbo].[sp_maintplan_delete_plan] #plan_id

Related

Execute dynamic sql query output?

Platform: SQL Server 2016
I've written a SQL statement that outputs a series of SQL commands and I want to execute the output of this query in the same script. This is the query that builds the commands I want to execute.
select
'ALTER SCHEMA dbo TRANSFER SYSNET.' + name + ';'
from
sys.tables
where
schema_name(schema_id) = 'sysnet'
order by
1;
I know I need to capture the output in a variable and then execute it. I'm sure it's simple but everything I've tried didn't work and Google has failed me.
==================================================
Thanks for the answers! scsimon technically gave the best answer since it provided the means of executing the output of any dynamic SQL and that's what I asked for. With that said, Ross Bush provided the simplest way for me to accomplish this specific task of transferring schema ownerships. In the end I used this...
EXEC sp_MSforeachtable #command1='ALTER SCHEMA dbo TRANSFER ?;'
,#whereand='AND schema_name(schema_id) = ''sysnet'''
Just loop through those seems to be what you want.
select row_number() over (order by (select null)) as RN, 'ALTER SCHEMA dbo TRANSFER SYSNET.'+ name + ';' as CMD
into #mytemp
from sys.tables where
schema_name(schema_id) = 'sysnet'
declare #sql varchar(max)
declare #i int = 1
while #i <= (select max(RN) from #mytemp)
begin
select #sql = CMD from #mytemp where RN = #i
print #sql
--exec(#sql)
set #i = #i + 1
end
drop table #mytemp
This is not the best advice as the function below is an undocumented SQL Server function and may not be around in the future. That being said, I would use the sp_MSforeachtable table to issue a command for each table in the target database.
EXEC sp_MSforeachtable 'SELECT COUNT(*) FROM ?'

How to limit the rows on remote/linked server

I have a linked server that I have to fetch data from. I'm joining on a table that I expect very few rows from. The query is below, and seems to be returning all of the rows to the original server to do the sort there.
I'm looking for a way to tell the query to filter on the target machine, with a query hint or something else.
Query
INSERT INTO #DealerHierarchy(DealerId, Level)
SELECT cd.ParentId, cd.Level
FROM [dbo].[AssignedDealer] ad
JOIN [nlsdb].[nls].[dbo].[vw_parentDealers] cd ON cd.RootId = ad.DealerId
WHERE ad.UserId = #userId
AND ad.IsActive = 1
AND (#DealerId IS NULL OR ad.DealerId = #DealerId)
When I add the following line, it seems to change and only send back the needed rows
and cd.RootId = 72311
I have tried moving out the local query into a separate temp table, and then select from the view WHERE DealerId IN (select from temp table) but it still runs slowly. Adding the REMOTE hint in the JOIN also does nothing.
Query plan:
https://www.brentozar.com/pastetheplan/?id=r1iazaaFZ
Slow code executed on linked server
declare #p1 int
set #p1=7
exec sp_prepexec #p1 output,N'#P1 numeric(10)',N'SELECT "Tbl1007"."ParentId" "Col1010","Tbl1007"."Level" "Col1011" FROM "nls"."dbo"."vw_parentDealers" "Tbl1007" WHERE #P1="Tbl1007"."RootId"',72311
select #p1
Fast code executed on linked server
declare #p1 int
set #p1=10
exec sp_prepexec #p1 output,NULL,N'SELECT "Tbl1007"."ParentId" "Col1010","Tbl1007"."Level" "Col1011" FROM "nls"."dbo"."vw_parentDealers" "Tbl1007" WHERE "Tbl1007"."RootId"=(72311.)'
select #p1
You can force a specific query to be run on the remote database by using OPENQUERY. OPENQUERY doesn't accept a parameter, so you can make it dynamic by further wrapping it in EXEC.
Example
DECLARE #SearchString NVARCHAR = ...
DECLARE #OpenQueryString NVARCHAR = 'SELECT * FROM OPENQUERY(remotedb, ''' + #SearchString + ''')'
EXEC (#OpenQueryString)

SQL Server - Creating a Plan Guide without using an alias

I'm trying to create a plan guide in SQL Server 2012 SP3 Enterprise Edition for a specific query run by an application, which means I cannot alter the query in any way.
The query looks like this:
(#P1 nvarchar(5),#P2 bigint)
DELETE FROM INVENTSUMDELTA WHERE ((DATAAREAID=#P1) AND (TTSID=#P2))
To create the plan guide, I used the following query:
EXEC sp_create_plan_guide
#name = N'INVENTSUMDELTAINDEX',
#stmt = N'DELETE FROM INVENTSUMDELTA WHERE ((DATAAREAID=#P1) AND (TTSID=#P2))',
#type = N'SQL',
#module_or_batch = NULL,
#params = N'#P1 nvarchar(5),#P2 bigint',
#hints = N'OPTION (TABLE HINT ( INVENTSUMDELTA, INDEX( I_2397TTSDIMIDX )))';
However, I received an error:
Msg 8724, Level 16, State 1, Line 1
Cannot execute query. Table-valued or OPENROWSET function 'INVENTSUMDELTA' cannot be specified in the TABLE HINT clause.
I checked the documentation and found the following:
TABLE HINT (exposed_object_name [ , [ [, ]...n ] ] )
Applies the specified table hint to the table or view that corresponds to exposed_object_name. [...]
exposed_object_name can be one of the following references:
When an alias is used for the table or view in the FROM clause of the query, exposed_object_name is the alias.
When an alias is not used, exposed_object_name is the exact match of the table or view referenced in the FROM clause. For example, if the table or view is referenced using a two-part name, exposed_object_name is the same two-part name.
From this I gather that it should be possible to create a plan guide for a query that isn't using an alias. However, I cannot get it to work.
So my question is: how do I create a plan guide without using aliasing and without altering the original query?
The error message is misleading. It has nothing to do with the nature of the object (you will get the same error with a nonexistent object). The problem is that it will not work for DELETE statements -- any TABLE HINT referring to a table that is the target of a DELETE will produce this error. This is not restricted to plan guides either -- a plain DELETE with an option will fail as well:
DELETE FROM does_not_exist
OPTION (TABLE HINT (does_not_exist, INDEX (does_not_exist)))
Cannot execute query. Table-valued or OPENROWSET function 'does_not_exist' cannot be specified in the TABLE HINT clause.
This appears to be a bug, because if the statement is augmented with a WITH (ROWLOCK) hint at both the table and query level, the error disappears:
DELETE FROM does_not_exist WITH (ROWLOCK)
OPTION (TABLE HINT (does_not_exist, ROWLOCK, INDEX (does_not_exist)))
Invalid object name 'does_not_exist'.
The same issue is covered in this question, and the solution is to rewrite the query in a form that does allow applying the hint.
In this case, we can't rewrite the query directly, but we can still get the desired effect by using a fixed query plan guide:
-- Alternate query using hint.
DECLARE #sql NVARCHAR(MAX) = N'WITH T AS (
SELECT *
FROM INVENTSUMDELTA WITH (INDEX (I_2397TTSDIMIDX))
WHERE ((DATAAREAID=#P1) AND (TTSID=#P2))
)
DELETE T';
DECLARE #params NVARCHAR(MAX) = N'#P1 nvarchar(5),#P2 bigint'
-- Put the execution plan in the cache.
EXEC sp_executesql #sql, #params = #params, #P1=NULL, #P2=NULL;
-- Retrieve it.
DECLARE #query_plan NVARCHAR(MAX);
SELECT #query_plan = query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.[sql_handle]) AS st
CROSS APPLY sys.dm_exec_text_query_plan(qs.[plan_handle], DEFAULT, DEFAULT) AS qp
WHERE st.[text] LIKE '(' + #params + ')%' + #sql;
-- Create a plan guide associating the query with the new execution plan.
EXEC sp_create_plan_guide
#name = N'INVENTSUMDELTAINDEX',
#stmt = N'DELETE FROM INVENTSUMDELTA WHERE ((DATAAREAID=#P1) AND (TTSID=#P2))',
#type = N'SQL',
#module_or_batch = NULL,
#params = #params,
#hints = #query_plan;
As always, plan guides should be the last resort if nothing else helps (updating statistics, creating new indexes, dropping suboptimal indexes). This answer assumes you've reviewed all the other options and the plan guide is necessary.

SQL variable for Database Name

I am trying to pass a database name in as a parameter and execute some dynamic SQL. As a test I created this:
declare #HRMSDatabase_1 nvarchar(50) = N'FirstDatabase',
#Example_1 nvarchar(max) =
'select #HRMSDatabase'
execute sp_executesql #Example_1, N'#HRMSDatabase nvarchar(50)', #HRMSDatabase_1
which returns FirstDatabase as I expected.
When I try this:
declare #HRMSDatabase_2 nvarchar(50) = N'FirstDatabase',
#Example_2 nvarchar(max) =
'select
''Test''
from
#HRMSDatabase.dbo.hrpersnl hp'
execute sp_executesql #Example_2, N'#HRMSDatabase nvarchar(50)', #HRMSDatabase_2
I get an error message:
Msg 102, Level 15, State 1, Line 29
Incorrect syntax near '.'.
Is what I am trying to do possible? I cannot simply use a USE FirstDatabase as I have a few databases I have to query in the same dynamic SQL using inner joins.
Also, I cannot use SQLCMD as this script gets executed from a GUI.
Basically, I don't believe you can parameterize the database name in the table specifier. Instead try this,
DECLARE #HRMSDatabase NVARCHAR(50) = N'FirstDatabase';
DECLARE #Example3 NVARCHAR(MAX) ='SELECT
''Test''
FROM
' + QUOTENAME(#HRMSDatabase) + '.[dbo].[hrpersnl] hp';
EXEC sp_executesql #Example3;
As you'll note, it's important that the #HRMSDatabase is not recieved from user input as this would be susceptible to injection attacks.

How to Execute SQL Server Stored Procedure in SQL Developer?

I've been given a user account to a SQL Server database that only has privileges to execute a stored procedure. I added the JTDS SQL Server JDBC jar file to SQL Developer and added it as a Third Party JDBC driver. I can successfully log in to the SQL Server database. I was given this syntax for running the procedure:
EXEC proc_name 'paramValue1' 'paramValue2'
When I run this as either a statement or a script, I get this error:
Error starting at line 1 in command:
EXEC proc_name 'paramValue1' 'paramValue2'
Error report:
Incorrect syntax near the keyword 'BEGIN'.
I tried wrapping the statement in BEGIN/END, but get the same error. Is it possible to call the procedure from SQL Developer? If so, what syntax do I need to use?
You don't need EXEC clause. Simply use
proc_name paramValue1, paramValue2
(and you need commas as Misnomer mentioned)
You are missing ,
EXEC proc_name 'paramValue1','paramValue2'
You need to do this:
exec procName
#parameter_1_Name = 'parameter_1_Value',
#parameter_2_name = 'parameter_2_value',
#parameter_z_name = 'parameter_z_value'
EXECUTE [or EXEC] procedure_name
#parameter_1_Name = 'parameter_1_Value',
#parameter_2_name = 'parameter_2_value',
#parameter_z_name = 'parameter_z_value'
I know this is the old one. But this may help others.
I have added SP calling function between BEGIN/END. Here is a working script.
ALTER Proc [dbo].[DepartmentAddOrEdit]
#Id int,
#Code varchar(100),
#Name varchar(100),
#IsActive bit ,
#LocationId int,
#CreatedBy int,
#UpdatedBy int
AS
IF(#Id = 0)
BEGIN
INSERT INTO Department (Code,Name,IsActive,LocationId,CreatedBy,UpdatedBy,CreatedAt)
VALUES(#Code,#Name,#IsActive,#LocationId,#CreatedBy,#UpdatedBy,CURRENT_TIMESTAMP)
EXEC dbo.LogAdd #CreatedBy,'DEPARTMENT',#Name
END
ELSE
UPDATE Department SET
Code = #Code,
Name = #Name,
IsActive = #IsActive,
LocationId = #LocationId,
CreatedBy = #CreatedBy,
UpdatedBy = #UpdatedBy,
UpdatedAt = CURRENT_TIMESTAMP
where Id = #Id
You need to add a , between the paramValue1 and paramValue2. You missed it.
EXEC proc_name 'paramValue1','paramValue2'
EXEC proc_name #paramValue1 = 0, #paramValue2 = 'some text';
GO
If the Stored Procedure objective is to perform an INSERT on a table that has an Identity field declared, then the field, in this scenario #paramValue1, should be declared and just pass the value 0, because it will be auto-increment.
There are two ways we can call stored procedure
CALL database name'. 'stored procedure name(parameter values);
example:- CALL dbs_nexopay_sisd1_dec_23.spr_v2_invoice_details_for_invoice_receipt_sub_swiss(1, 1, 1, 1);
From your MySQL workbench also you can do that.
i. Right-click on stored procedure.
ii. Send to SQL editor
iii. Procedure call.
If you simply need to excute your stored procedure
proc_name 'paramValue1' , 'paramValue2'...
at the same time you are executing more than one query like one select query and stored procedure you have to add
select * from tableName
EXEC proc_name paramValue1 , paramValue2...
The stored procedures can be run in sql developer tool using the below syntax
BEGIN
procedurename();
END;
If there are any parameters then it has to be passed.
Select * from Table name ..i.e(are you save table name in sql(TEST) k.
Select * from TEST then you will execute your project.

Resources