Thursday, January 3, 2019
Update SQL Server Agent Job Owner
I have been working on a project to move/migrate lots of jobs to a new server in another domain and we had to update quite a bit of jobs to set the owner to 'sa' prior to migration. Out of close to 600 jobs, there were about 200 jobs owned by not 'sa' but an account in Active Directory. So instead of touch all of those jobs manually and change the owner I come up with the following script and all done in less than 10 minutes including time took come up with the script. I decided to share it here and also use my blog to document it if I ever need it.
HTH,
Bulent
USE MSDB;
GO
SET NOCOUNT ON;
/********************************
This script is used to update the job owner to sa for
the jobs that is not already owned by sa.
********************************/
DECLARE
@MinRowId INT = 1
, @MaxRowId INT
, @jobId UNIQUEIDENTIFIER
, @owner_login_name NVARCHAR(128) = N'sa';
-- Store the job steps in a temp table to update the in the loop later
IF OBJECT_ID('tempdb..#Jobs') IS NOT NULL
DROP TABLE #Jobs;
CREATE TABLE #Jobs (
RowId INT IDENTITY (1,1) NOT NULL
, job_id UNIQUEIDENTIFIER NOT NULL
, jobname SYSNAME NOT NULL
, owner_sid VARBINARY(85)
);
-- Insert list of jobs not owned by 'sa'
-- Can change the select statement and
-- where clause to your need
INSERT INTO #Jobs (job_id, jobname, owner_sid )
SELECT j.job_id, j.name, j.owner_sid
FROM dbo.sysjobs AS j
WHERE J.owner_sid <> 0x01 -- sid for SA
ORDER BY j.name
SET @MaxRowId = @@ROWCOUNT;
WHILE @MinRowId <= @MaxRowId
BEGIN
SELECT @jobId = job_id
FROM #Jobs
WHERE RowId = @MinRowId;
EXEC sp_update_job @job_id = @jobId, @owner_login_name = @owner_login_name;
SET @MinRowId = @MinRowId + 1;
END
--Return list of jobs and original owner sid
SELECT * FROM #Jobs;
DROP TABLE #Jobs;
Monday, November 26, 2018
Find Actively Running SQL Server Agent Jobs
An ETL developer asked my help recently with a SQL Server Agent job needed to start running if the main job finished running. Occasionally main job run longer than expected and interfered with the secondary job which should run after the main job. In the first step of secondary job we added a step to continue if the following query returned no rows if it returns a row then we set the job to retry again in 10 minutes for 3 times which solved our issue.
HTH,
Bulent
USE msdb;
GO
SELECT
j.name AS job_name,
ja.start_execution_date,
ISNULL(last_executed_step_id,0)+1 AS current_executed_step_id,
Js.step_name
FROM dbo.sysjobactivity AS ja
LEFT OUTER JOIN dbo.sysjobhistory AS jh ON ja.job_history_id = jh.instance_id
INNER JOIN dbo.sysjobs AS j ON ja.job_id = j.job_id
INNER JOIN dbo.sysjobsteps AS js ON ja.job_id = js.job_id AND ISNULL(ja.last_executed_step_id,0)+1 = js.step_id
WHERE ja.session_id = (SELECT TOP 1 session_id FROM msdb.dbo.syssessions ORDER BY agent_start_date DESC)
AND ja.start_execution_date is not null
AND ja.stop_execution_date is null
--AND j.name = 'NameOfTheJob' -- Uncomment and supply the name of the job you need to find out if it's actively running
GO
Monday, October 31, 2016
Error 'The network address is invalid' Intalling Clustered SQL Server on VirtualBox VMs
While I was trying to set up a lab for testing out SQL Server 2016 on clustered two node Windows Server Failover cluster running Windows Server 2012 R2, I kept getting the error in the screen shot below. I had no problem setting up the AD Domain controller, and two windows server nodes which will take part in the cluster. DNS worked just fine, long story short there was no issue at all. I tried two options where one was granting additional permissions to windows cluster network object (CNO) which did not work, and other one was to pre-stage the SQL Cluster prior to installation which did not work either.
Further search came up with the solution from Jonathan Kehayias's blog dated September 19, 2011. The simple solution was to remove 'Oracle VM VirtualBox Guest Additions'. I un-installed that software rebooted the servers and was able to install the SQL Server Cluster successfully. If you're not already following not only Jonathan's blog but everyone at SQLskills, I recommend to do so since you will benefit from their contribution immensely.
HTH,
Bulent
Monday, August 29, 2016
Get Size Information For All Tables in All Databases
I have been working on a small project to log and track the size and growth of the tables in all databases. So that overtime I can show the growth size and estimate the disk space allocation requirements for databases in production environment. Here is the script I used to capture the information. I used SQL Server Agent job scheduled to run once a day after midnight and store the results in a repository to be monitored and reported on later. You can uncomment the where clause to exclude system tables and tables with no records in them if you want.
SET NOCOUNT ON;
-- Get Table Statistics (Row Count, total space used)
IF OBJECT_ID('tempdb..#TableStatistics') IS NOT NULL
BEGIN
DROP TABLE #TableStatistics;
END
CREATE TABLE #TableStatistics (DatabaseName SYSNAME, SchemaName SYSNAME, TableName VARCHAR(128), TableRowCount BIGINT, TotalSpaceKB VARCHAR(20), UsedSpaceKB VARCHAR(20), UnusedSpaceKB VARCHAR(20));
EXEC sp_msforeachdb 'USE [?];
INSERT INTO #TableStatistics
SELECT
''?'' as DatabaseName
, s.Name AS SchemaName
, t.NAME AS TableName
, p.rows AS TableRowCount
, SUM(a.total_pages) * 8 AS TotalSpaceKB
, SUM(a.used_pages) * 8 AS UsedSpaceKB
, (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables AS t
INNER JOIN sys.indexes AS i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions AS p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units AS a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
--WHERE p.rows > 0 AND t.is_ms_shipped = 0 AND i.OBJECT_ID > 255
GROUP BY t.Name, s.Name, p.Rows
ORDER BY s.name, t.name' ;
SELECT *
FROM #TableStatistics;
DROP TABLE #TableStatistics;
HTH,
Bulent
Friday, July 29, 2016
The Principal "dbo" Does Not Exist
System.Data.SqlClient.SqlException: Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.
I run into the error message after restoring a backup that belongs to a client while trying to reproduce the issues they were having. When a database is restored the ownership of the database is assigned to the account running the restore command but in my case it was not that account. It was actually blank as seen in the database properties screenshot below.
So to fix the issue I run the command 'Alter Authorization On Database' to make a domain account owner of the database (see the screenshot below). In my case the domain account is the SQL Server Service account.
After running the command (see the screenshot below) the database property page shows the domain account as the owner of the database and the error message did not get logged into the application log any longer.
HTH,
Bulent
Friday, May 3, 2013
70-462 Administrating Microsoft SQL Server 2012 Databases
After being quite some time and studying for exam 70-462 I would like to tell you that I passed the exam on my first attempt. I say first because I started studying while back and things at work prevented me to allocate more time during the week and I slacked over the weekends. And before I ran out of time to take advantage of free second shot promotion I said just cram for several weeks and take the exam and if failed schedule the second shot free and study harder.
I used the book from Microsoft Press to study and set up a lab environment. I have to say it was a good book to use and helpful to learn the new features. The CD has the sample exam to test your knowledge of the material just covered in the book. It also has the study mode as well. The questions in the CD exam as far as I remember were close to real exam questions. The exam tests the knowledge of the steps to execute to properly implement something as well as writing administrative type of T-SQL statements.
For somebody with no prior experience the book is not enough to pass the exam. However, I have been certified in SQL Server 2008 and working with SQL Server almost 7 years when I started the real exam I thought the questions were not as hard as I expected.
I definitely recommend everybody to study and take the exam since it shows an initiative on professional development. I am sure we can argue about the credibility and if certification count for experience. I think that it definitely does not count for the experience but just a reminder of one's professional development and willing to learn the product.
Regards,
Bulent
Monday, February 20, 2012
Compressing SQL Server Backup Files
Starting with SQL Server 2008 Enterprise Edition we have the option of compressing backup files (this includes both BACKUP DATABASE and BACKUP LOG statements which mean not only database backups but log file backups will be compressed) to save disk space and also decrease the duration of the backup and restore operations. The backup compression was an enterprise edition only feature with SQL Server 2008 but with SQL Server 2008 R2 this feature is supported by standard and higher editions. So that was welcome news for me since I support number of SQL Server 2008 R2 Standard Edition.
I have been using T-SQL script to backup databases. The script checks the edition of the SQL Server and then builds the backup command to compress the backup file if it’s enterprise edition or just backups the database if it was a standard edition.
Before the end of 2011 I have completed deploying/upgrading to SQL Server 2008 R2. That meant that my script no longer needed to check the edition of SQL Server 2008 R2 since the compression is already supported in standard and higher editions. So I turned to global configurations and enable the backup compressions. I would like to remind the readers that enabling the backup compression creates additional CPU overhead which depends on you workload might impact your server performance. I suggest that you test your backup process and if necessary using Resource Governor (this is Enterprise Edition only feature) create a low priority compressed backup in a session whose CPU usage is limited by Resource Governor when CPU contention occurs.
Let’s start with checking the backup compression setting for the server by using the script below.
USE master
SELECT *
FROM sys.configurations
WHERE name = 'backup compression default'
ORDER BY name
Let’s check the returned result for the value_in_use column. This shows us the running value curently in effect for this option and is_dynamic column tells us the changes take effect after the RECONFIGURE statement executed. Now it’s time to execute the below script to enable the backup compression since the value_in_use is 0 for the server I am currently working.
USE master
EXEC SP_CONFIGURE 'backup compression default',1
RECONFIGURE
Let’s check the value_in_use by executing the first select statement.
USE master
SELECT *
FROM sys.configurations
WHERE name = 'backup compression default'
Now we should see that the value_in_use is 1 and we don’t need to use the optional keyword COMPRESSION in the backup database command.
By default when backup is compressed checksums are performed to detect media corruptions but if for any reason you need, you can explicitly disable the compression by using NO_COMPRESSION keyword in your backup statement.
I have seen anywhere from 35% to 80% compression ration and backup duration decrease from several hours to 30-45 minutes for the databases I administor. Your mileage will vary and you should TEST, TEST, TEST and deploy your changes for your environments. Here is the link to find out more about backup database command in MSDN.
HTH,
Bulent
Friday, February 3, 2012
Dropping Multiple SQL Server Objects in Single Line
As humans we try to find a way to work faster and efficient. As data professionals, typing less probably is another thing we want. My SQL Server tip today is about dropping multiple objects (tables, views, stored procedures, and even databases) in single drop statement. This is powerful but can be dangerous in production so please use caution. Here is a script that creates couple of tables and then drops both tables in single drop statement.
Sincerely,
Bulent
-- CREATE TABLES
USE tempdb
GO
CREATE TABLE dbo.TableT1 (t1c1 TINYINT)
CREATE TABLE dbo.TableT2 (t2c1 TINYINT)
GO
INSERT INTO dbo.TableT1 VALUES(1)
INSERT INTO dbo.TableT2 VALUES(2)
GO
-- CHECK THE TABLES CREATED
SELECT *
FROM sys.tables
WHERE name LIKE 'TableT_'
GO
-- DROP BOTH TABLES IN SINGLE DROP STATEMENT
DROP TABLE dbo.TableT1, dbo.TableT2
GO
-- CHECK THE TABLES DROPPED
SELECT *
FROM sys.tables
WHERE name LIKE 'TableT_'
GO
Friday, January 27, 2012
Cycling SQL Server Error Log
In the environments that I support I change the configuration so that I keep more than 6 files. I set up to store 99 files (which is the max allowed files for the SQL Server error log). Then I create a job that runs every night right after midnight. This way when I come in every morning there is a brand new log file and since the daily log files are much smaller it makes the file easy to open and check. I use the script below to change the number of log files (note you can do this using SSMS GUI and just make a right click on SQL Server Logs under Management folder than click on Configure and change the value to what you need). After the change using second script I create SQL Server Agent Job that is scheduled to run right after midnight to cycle the error log. This make the daily task of checking the error logs easier (at least for me). Use the scripts below in a test environment and once you find out it could add some value to your daily tasks you could use it in your production environment.
HTH,
Bulent
Script 1:
This changes the number of log files stored to a value you set at the end and uses extended stored procedure to update the registry. Remember this can be done through GUI but it does executed the same in the background.
Script 2:
This script creates a job (make sure you sql server agent is running) and schedules it to run at 12:00:01 am everyday.
Monday, December 20, 2010
Monday, September 20, 2010
SQL Server Error 5042 Can Not Remove File X Because It's Not Emty
HTH
Friday, September 17, 2010
SQL Server Collate Clause And Case Sensitivity
HTH,
USE tempdb
GO
CREATE TABLE dbo.CaseSensitiveTest(
RowId TINYINT IDENTITY (1,1),
CIFName VARCHAR (30),
CILName VARCHAR (30),
CSFName VARCHAR (30) COLLATE Latin1_General_CS_AS,
CSLName VARCHAR (30) COLLATE Latin1_General_CS_AS
)
GO
INSERT INTO dbo.CaseSensitiveTest
SELECT 'MICKEY', 'MOUSE', 'Mickey','Mouse'
UNION ALL
SELECT 'mickey', 'mouse', 'mickey','mouse'
UNION ALL
SELECT 'mickey', 'mouse', 'Mickey','Mouse'
UNION ALL
SELECT 'MICKEY', 'MOUSE', 'MICKEY','MOUSE'
UNION ALL
SELECT 'bunny', 'rabbit', 'Bunny','Rabbit'
UNION ALL
SELECT 'BUNNY', 'RABBIT', 'BUNNY', 'RABBIT'
GO
SELECT * FROM dbo.CaseSensitiveTest
SELECT *
FROM dbo.CaseSensitiveTest
WHERE CIFName COLLATE Latin1_General_CS_AS = CSFName
AND CIFName COLLATE Latin1_General_CS_AS = UPPER(CIFname)
DROP TABLE dbo.CaseSensitiveTest