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;
Friday, August 12, 2016
Find Size of the Indexes for Indexed Views
I have several scripts in my tool box to look into the indexes for tables, but did not have one for indexed views. I wanted to share a script that return the size of clustered and non clustered indexes for indexed views if exist in the context of the database where the script is executed.
HTH,
Bulent
SELECT
OBJECT_SCHEMA_NAME(v.object_id) AS 'SchemaName'
, v.NAME AS 'ViewName'
, i.index_id
, i.name AS 'IndexName'
, p.rows AS 'RowCounts'
, SUM(a.total_pages) * 8 AS 'TotalSpaceKB'
, SUM(a.used_pages) * 8 AS 'UsedSpaceKB'
, SUM(a.data_pages) * 8 AS 'DataSpaceKB'
FROM sys.views AS v
INNER JOIN sys.indexes AS i ON v.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
GROUP BY v.object_id, v.NAME, i.object_id, i.index_id, i.name, p.Rows;
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
Tuesday, June 4, 2013
How to Change SQL Server Authentication Mode
I was asked to fix a connectivity problem for SQL Server 2008 deployed to test virtual machine. I was told that nobody was able to connect neither using sql server login nor windows login (neither SA account with generic password nor the local administrator of the windows server)
Since I have seen this in the past and heard about it, I knew what caused this problem. Basically it was the result of not granting access to any log in with right credentials. First thing I tried is to make sure that I am using a log in that has sys admin rights. For this I followed the steps in my earlier blog post (click this link to read that blog). Make sure to use strong password for the sql log in you just created.
Upon restarting SQL Server I attempted to use the new account I just created with no success. I kept getting login failed message. Then I wanted to check the SQL Server error log to see if any error message logged. In my situation I was able to locate the error logs stored at "C:\Program Files\Microsoft SQL Server\MSSQL10.Test01\MSSQL\Log" however in your case it might be different based on installation path and version of the SQL Server. Just by looking at the path you can tell that I am dealing with named instance installation of SQL Server and the name of the instance is 'Test01' and MSSQL10 means it's SQL Server 2008. If you're dealing with another version like SQL 2008 R2 you would see 'MSSQL10_50' and if you're dealing with SQL Server 2012 it would be 'MSSQL11'. And if you're dealing with default instance then instead of 'Test01' you would see 'MSSQLSERVER' in the path.
Anyway, I opened the file named 'errorlog' using notepad and started to scanning the entries. Within seconds I found an error message stating that 'login failed because of server is configured with Windows Authentication mode but the login is sql login'. At this moment I knew that I had to change the authentication mode to 'SQL Server and Windows Authentication mode' to gain access using the sql login I just created.
If you search the Internet you will find how to change the authentication mode during installation or changing the authentication mode using SSMS. However I had no way of connecting to SQL server via SSMS to change the authentication mode. But there is another way that it can be done. Of course this is not documented anywhere in MS knowledge base since it involves registry hacking!!!.
In my case this was a test server and I was OK if I ended up messing up the server and need to rebuilt it. If you're in the same situation and willing to do the same then keep on reading.
Open the command prompt and type "regedit" (without quotation marks) and hit enter. Make sure to backup the registry before making any changes. Then browse to the location for your SQL Server installation on the left pane. In my case it was the named instance of SQL Server which was named 'Test01'.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.Test01\MSSQLServer
And here is the path to default instance:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLServer\MSSQLServer
Then on the right pane find "LoginMode" make a right click and click on 'Modify' then finally change the 'Value data' to 2, click ok and exit the registry editor.
Stop the SQL Server service and then restart it. Now your instance authentication mode has been changed to 'SQL Server and Windows Authentication mode' and you can use the sql login that you created to access and configure the server.
HTH,
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
Thursday, January 12, 2012
SQL Function QUOTENAME()
Thursday, December 8, 2011
The distribution agent failed to create temporary files
Tuesday, September 13, 2011
70-433 TS: Microsoft SQL Server 2008, Database Development
SQL Server 2008 R2 Express Edition and Full Text Search
Thursday, June 9, 2011
Dropping Local Temp Table
Saturday, March 26, 2011
More on SQL Server 2008 Variable Enhancements
Sunday, March 20, 2011
SQL Server 2008 Variable Declaration
Saturday, March 5, 2011
70-432 TS: Microsoft SQL Server 2008, Implementation and Maintenance
Monday, December 20, 2010
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