Category: SQL Server

SQL Server Blog Archives, by Peter Whyte (Database Administrator).
Includes: Database Admin, Management Studio (SSMS), Windows Admin, PowerShell, WSL, MSSQL Backups, Restores & more…

  • Disabling Change Data Capture in SQL Server

    Disabling Change Data Capture in SQL Server

    This post contains a demo on how to disable CDC (Change Data Capture) in SQL Server 2022. The sp_cdc_disable_table and sp_cdc_disable_db in-built MSSQL SPs are what we should use to disable CDC in SQL Server which is explained more below.

    The sp_cdc_disable_table and sp_cdc_disable_db are the in-built MSSQL SPs to do this which are explained below.

    Disabling CDC can be a common task for a SQL DBA as we need to do this each time a new column is created on the source table. We run sp_cdc_enable_table to add all columns in a table to CDC, but then when a new column is created we need to drop CDC on the table and re-enable it in SQL.

    My previous blog post explains how to enable CDC in SQL Server and will show you how to enable CDC. This post is a guide for the CDC disable action.

    Before proceeding with a change like this on a production SQL environment, we should read Microsoft Docs on Enabling & Disabling CDC, and test the change to get familiar enough with CDC.

    How to Disable CDC SQL Server

    Disabling CDC for a table in MSSQL will drop all existing captured change data. If you are intending on performing this on a production SQL Server, you should verify whether we need to back up & copy existing CDC data.

    To disable Change Data Capture on a table in SQL Server, we should first check for existing CDC configuration information by running sp_cdc_help_change_data_capture. Using this info we can populate the parameters for sp_cdc_disable_table, particularly the capture_instance name.

    USE [demoBlog];
    GO
    
    -- Check current CDC config
    EXEC sys.sp_cdc_help_change_data_capture 
    
    -- Disable CDC for a table
    EXECUTE sys.sp_cdc_disable_table
    	@source_schema = N'dbo',
    	@source_name = N'posts',
    	@capture_instance = N'dbo_posts'
    CDC Disable Table

    If you are removing CDC from all tables permanently, we can disable CDC on the database too.

    Run sp_cdc_disable_db to disable CDC on a database in MS SQL as per the example below.

    USE [demoBlog];
    GO
    
    -- Disable CDC for a database
    EXEC sys.sp_cdc_disable_db
    GO
    
    -- Check if CDC is enabled on databases
    SELECT is_cdc_enabled,* FROM sys.databases;
    sp_cdc_disable_db

  • How to Enable CDC in SQL Server

    How to Enable CDC in SQL Server

    This is a post on how to enable Change Data Capture (CDC) in SQL Server. Enabling this on a database and table will allow the recording of activity when tables and rows have been modified. This is a feature available for us to configure within SQL Server and Azure SQL out of the box.

    CDC uses the SQL Agent to record inserts, updates and deletes that happen on a table. Enabling this might be useful to help give a business insight on changes to Personal Identifiable Information (PII) over time for GDPR requirements. Or, another example could be real-time tracking of orders for pricing updates to a product.

    For more examples and information on what CDC is, we can refer to MS Docs : What is change data capture (CDC)?

    If you are considering enabling this feature, as always we should test and read through the software documentation to ensure all potential impacts and limitations have been reviewed. Some main considerations on the systems side with this one include the additional disk space your CDC tables will need, and performance depending on the number of tables/changes happening.

    The demo below covers the following:
    # Enable CDC for a Database
    # Enable CDC for a Table

    Enable CDC for a Database

    Before enabling CDC on a database we want to first check if it’s already enabled, and also check if the database owner is set to something other than ‘sa’, else you’ll receive an error message when enabling.

    In the demo TSQL below we’re checking the sys.databases system table is_cdc_enabled column, and we have to change the DemoBlog database owner :

    -- Check if Database is has CDC Enabled
    SELECT is_cdc_enabled, *
    FROM sys.databases;
    
    -- (IF_REQUIRED) Change Database Owner to 'sa'
    -- Error if <> 'sa' = "Could not update the metadata that indicates database demoBlog is enabled for Change Data Capture"
    ALTER AUTHORIZATION ON DATABASE::[demoBlog] TO [sa]
    GO
    CDC Check if Enabled

    Enabling CDC for a SQL Server database is done using the sys.sp_cdc_enable_db system stored procedure, as shown in this example :

    USE [demoBlog];
    GO
    -- Enable CDC for Database ms sql
    EXEC sys.sp_cdc_enable_db
    GO
    /* New system tables > 
    	[cdc].[captured_columns];
    	[cdc].[change_tables];
    	[cdc].[ddl_history];
    	[cdc].[index_columns];
    	[cdc].[lsn_time_mapping];
    	[dbo].[systranschemas];
    */
    Enable CDC

    We can see our new CDC system tables in the screenshot above, and I’ve re-run the sys.databases query to show the changes there too.

    Enable CDC for a Table

    I’ve just enabled CDC on this demo database, so I know there are no tables already enabled. We can check the is_tracked_by_cdc column in the sys.tables system table, similar to the check we did before enabling it on the database.

    To control the placement of change table data, we can create Filegroups ahead of enabling CDC on tables. Microsoft recommends we do this so that our change tables are separate from source tables.

    -- Create FileGroup for CDC
    ALTER DATABASE [demoBlog] ADD FILEGROUP [DemoBlog_CT];
    
    ALTER DATABASE [demoBlog]
    ADD FILE
    (
        NAME = demoBlog_data1,
        FILENAME = 'D:\MSSQL_DATA\demoBlog_data1.ndf',
        SIZE = 500MB,
        FILEGROWTH = 50MB
    ) TO FILEGROUP [DemoBlog_CT];
    
    SELECT * FROM sys.filegroups;
    SELECT * FROM sys.database_files;
    SQL Server Add FileGroup

    We use sys.sp_cdc_enable_table to enable CDC on a table, as per the example below. When a table is enabled for CDC, a record will be logged in the transaction log for each DML operation applied to the table from this point onwards.

    USE [demoBlog];
    GO 
    
    -- Enable CDC on Table
    EXEC sys.sp_cdc_enable_table
    	@source_schema = N'dbo',
    	@source_name   = N'posts',
    	@role_name     = NULL,
    	@filegroup_name = N'DemoBlog_CT'
    GO
    -- Job 'cdc.demoBlog_capture' started successfully.
    -- Job 'cdc.demoBlog_cleanup' started successfully.
    CDC Enable Table

    Our new SQL Agent jobs for the CDC Collection are as per the screenshot below.

    Interesting note, “If both CDC and replication are enabled for a database, the log reader handles the population of the CDC change tables.” – Microsoft Docs

    CDC Agent Jobs

    For demo purposes, here is an example insert of a row into our table, and then a query of CDC data.

    Verify CDC is working

    My next post covers Disabling CDC, which may be useful if you receive errors along the way during testing.

  • SQL Server Default Port

    SQL Server Default Port

    The default port for the SQL Server Engine is 1433, which is a useful thing to know if you’re working as a Database Administrator (DBA) or Database Reliability Engineering (DBRE) type role.

    Though-out my career I’ve seen SQL Server run on the default 1433 port 99% of the time. For the other 1 percent, it didn’t matter much to me what port it was using.

    Occasionally as a DBA, you will need to arrange network line of sight (firewall rule changes) to be carried out by Network teams for MSSQL host-to-host connectivity. This is done via some request form a lot of the time, and we need to send source/destination addresses. Including IP addresses, we would also need to verify which port the SQL Server is using. Always best to double-check which MSSQL is running before submitting these types of requests, the demo below will help get this info.

    We also need to consider the local Windows Firewall on each SQL Server host. The rule should be scoped to the individual IP connecting, or subnet (10.20.30.0\24, all 256 addresses).

    SQL Server uses a lot of ports for various features & services, e.g. SQL Browser 1434 / SSIS 135. For anything beyond this basic SQL port info, MS Docs will provide you with what’s needed – there’s a lot, which I’m currently digesting at the time of writing.

    Anyway, with network stuff out of the way, this post contains the following demos:
    # How to Check Default SQL Server Port
    # How to Add New Windows Firewall Rule for Default MSSQL Port (1433)

    How to Check Default SQL Server Port

    Open SQL Server Configuration Manager, which is accessible via the Start Menu on any SQL Server host.

    Navigate as shown on the screenshot below, to SQL Server Network Configuration > Protocols for MSSQLSERVER > TCP/IP Properties > IP Address Tab

    SQL Server Check Default Port

    You can amend ports here too, but read MS Docs and test first if doing on Production, of course.

    How to Add New Windows Firewall Rule for Default MSSQL Port

    This is an added note on how to add the SQL Server 1433 Port & SQL Server Browser 1434 Ports. We can use the GUI >

    Windows Firewall Add New Rule

    And we can do the same with PowerShell, using the New-NetFirewallRule cmdlet.

    # Add SQL Server Local Firewall Rule
    New-NetFirewallRule -DisplayName "SQLServer default instance" -Direction Inbound -LocalPort 1433 -Protocol TCP -Action Allow
    # Add SQL Server Browser Local Firewall Rule
    New-NetFirewallRule -DisplayName "SQLServer Browser service" -Direction Inbound -LocalPort 1434 -Protocol UDP -Action Allow

    I hope this was a useful SQL Tip. I have another post that relates to Windows Ports- How to Find Which Process is Listening on a Port in Windows

  • How to Connect to SQL Server with a Different Domain User Account

    How to Connect to SQL Server with a Different Domain User Account

    This post is a guide on how to connect to SQL Server with Windows Authentication, but using a different Domain User rather than your own.

    The regular Windows SQL Server User connects & runs their queries via SQL Server Management Studio (SSMS). If you’re in a corporate environment, you’ll likely be logged into your computer with an Active Directory (AD) User. In this example, if we open SSMS we will likely connect with our currently logged-in AD account.

    This guide shows how to authenticate to MSSQL using an AD account that is not the same as your own logged-in user, which is particularly useful for testing newly created SQL Server AD User access and permissions.

    Open SSMS with Other Domain User

    A regular SQL Server Management Studio (SSMS) user in Windows has the application pinned to their taskbar. Search with the Windows button and follow the same on the SSMS app icon.

    Right-Click SSMS Icon –> Hold CTRL + Right-Click Icon –> Select Run As Different User

    SSMS Run as a Different User
    Run as a different user prompt

    Simple as that. No need for much longer explanations. All I can refer you to is my SSMS Tips tag for more Management Studio related blog posts.

  • How to Rename a Computer that Hosts SQL Server

    How to Rename a Computer that Hosts SQL Server

    When changing the hostname of a computer that is running SQL Server, we have to update system metadata so that remote connections and applications do not lose connectivity. The hostname system metadata is stored in sys.servers and reported by @@SERVERNAME.

    This post is a guide on how to update MS SQL metadata after a hostname change. This is often needed soon after a fresh SQL Server installation – you’ve installed SQL but then realise you need to change the Windows Server Computer Name.

    Considerations when changing a SQL Server hostname include:
    # Failover Clusters, the renaming process differs.
    # If Replication is configured on the host, I’d question why you are doing this.
    # If Mirroring, turn off Mirroring pre-change and then re-establish with new computer name. This could be high risk.
    # If the host is running SSRS, a configuration change may be required.
    # Hardcoded hostnames for all scripts/apps will have to be updated.

    This is all as described on Microsoft’s Documentation page. As always, give MS Docs a proper read and test your changes before performing in a Production environment. Hopefully, this is a new install and a single instance host you’re renaming.

    The demo below includes:
    # Change Windows Computer Name
    # Update MSSQL with the new Hostname
    # Verify Change

    Change Windows Computer Name

    To change the hostname of a Windows computer, we can do it via GUI or command (PowerShell).

    Rename Computer

    The PowerShell cmdlet for this is Rename-Computer, ensure you are running PowerShell as Administrator:

    PowerShell Rename-Computer

    A reboot is required post-change as per the warning on the terminal.

    See MS Docs as linked above for parameters required if you are connected to a Domain, or for an example of renaming remote hosts.

    Update MSSQL with the new Hostname

    Now that the computer has been renamed, when we try login into SQL Server via SSMS using the old hostname, the following error will appear:

    We need to change the server name to ‘localhost‘ or the new server name for us to get connected.

    SSMS Localhost

    Next, I’m going to run a new query to get the currently registered hostname and actual hostname.

    -- Get currently registered hostname 
    SELECT @@SERVERNAME AS 'Old Server Name' 
    
    -- Get actual hostname (undocumented proc)
    EXEC xp_getnetname
    Get Hostname SQL Server

    Next, drop the currently registered name (sp_dropserver) and then register the new hostname (sp_addserver).

    -- Remove server from list of known remote and linked servers on the local instance
    EXEC sp_dropserver 'pw-pc-pah';  
    GO
    
    -- Define name of local instance after computer rename
    EXEC sp_addserver 'WIN-PW-01', local;  
    GO
    SQL Server Rename Host Procedure

    For the change to be applied, we need to restart the SQL Server service.

    Verify Change in SQL Server

    Once the SQL Server Engine has been restarted, run the same command as before to return the currently registered hostname. It should display the new computer name:

    SQL Server Hostname Change

    Now you can verify any other apps or MSSQL features as per your test plan. Any existing connection strings will need to be updated with the new hostname if using it.

    I hope this all worked out for you if you followed along.

  • Get All Database Sizes in SQL Server

    Get All Database Sizes in SQL Server

    Measuring databases is important for knowing how much disk space a SQL Server requires today, as well as the future growth of the database files. It takes more than one run of a script to know all your disk provisioning needs. The script below in this post helps give a quick look at the database sizes on a SQL Server instance.

    There are many ways to get this information, but personally, I have always preferred to run a script like this to get database sizes in SQL Server throughout my career. You’ll spend a lot of time querying sys.databases and be familiar enough with this as a DBA too.

    Script to Show Database Sizes in SQL Server

    The script below will return all databases sizes in SQL Server –

    Get Database Sizes SQL Server

    I often bring up the Shrink File window in SSMS to view the database and log file sizes from there, as shown in the screenshot above. If checking one database this is a good way.

    For more information on this MS SQL Database sizes, have a look at the Measuring Databases Tag.

  • How to Backup a SQL Server Database

    How to Backup a SQL Server Database

    This post contains a demo on how to backup a SQL Server Database and includes some information on the types of backups available in MS SQL.

    The 3 types of backups that will be covered in this post are:
    # MS SQL Full Backup
    # MS SQL Transaction Log Backup
    # MS SQL Differential Backup

    Before backing up a database, you should verify the disk the backup is going to has enough space to hold the backup. You may also want to check when your databases were last backed up, to ensure running a backup is necessary at this time, or for general review.

    There’s a lot to understand with backups in SQL Server. Always refer to MS Docs when performing a change to a Production environment. This is just demo & information sharing.

    MS SQL Full Backup

    A Full Database Backup is a backup that will contain the whole database, all of the data included until the point in time the backup was taken. This is our main Restore Point.

    By running the command below, we are able to run a Full Backup of the database, with compression.

    Amend the database name in [square-brackets] and location/name on disk in ‘quotes’ –

    -- Run full database backup with compression
    BACKUP DATABASE [demoBlog] TO DISK = N'd:\D:\mssql_backups\demoBlog_full_01082022_1300.bak' WITH COMPRESSION, STATS;
    SQL Server Database Backup

    Backing up a database can sometimes take a very long time. It depends on various factors why a backup takes longer, but one common factor is, that the bigger your database gets, the longer it will take to backup & restore.

    I’ve seen a Full Backup in a Production environment take more than a day to complete (multi-terabyte). This is why a script to check estimated backup & restore time comes in useful for a DBA.

    MS SQL Transaction Log Backup

    Transaction Log Backups in SQL Server help log & store transactions that are made in your database which can then be used to bring databases back online to a point in time, in a disaster scenario.

    When running the command below we want to have an associated Full Backup that chains to this Transaction Log Backup. That means, having a Full Backup you performed, and your LSN chain hasn’t been broken by a manual Full Backup without including the Copy_Only parameter.

    To run a Transaction Log Backup –

    -- Run tlog backup 
    -- (amend database name & location/file on disk)
    BACKUP LOG [demoBlog] TO DISK = N'd:\mssql_backups\demoBlog_tlog_21082022_2130.bak' WITH COMPRESSION, STATS;
    SQL Transaction Log Backup

    Using the above Transaction Log backup, we can restore data that happened after the last Full Backup up until the point in time this Transaction Log backup was initiated.

    The reasoning behind using Transaction Log backups generally comes down to your business’s desire to ensure High Availability in your SQL Server environment. If you don’t need a recent restore point and can live with (e.g.) daily Full Backups, Transaction Logs are not for you.

    MS SQL Differential Backup

    Differential Backups capture only the data that changes since the last Full Backup has run. A Full backup can be considered the base of a Diff Backup (except for Copy_Only backups).

    The Differential Backup is one I see rarely in Production environments. A major benefit of Diffs is that they are quick to run. The size of a Diff Backup depends on the volume of data that has changed since its last rebase (last Full Backup).

    In the example below I’m running a simple Differential Backup of my demoBlog Database –

    -- Run diff backup
    BACKUP DATABASE [demoBlog] TO DISK = N'd:\mssql_backups\demoBlog_diff_21082022_2133.bak' WITH DIFFERENTIAL, COMPRESSION, STATS;
    SQL Differential Backup

    That’s us done, a quick review of the main types of database backup in SQL Server. For backup tips, check out the Database Backups tag.

  • Get Estimated Backup Restore Time in SQL Server

    Get Estimated Backup Restore Time in SQL Server

    This post contains a SQL script to get estimated completion times and process information for your currently running database backups & restores in SQL Server.

    Backing up a database can often take a very long time. It depends on various factors why a backup can take longer to complete. One more obvious reason is, that the bigger your database gets, the longer it will take to backup & restore.

    Other backup performance considerations include whether your server is busy with transactions/queries, or you may be running on old hardware, and I’ve seen having fragmented heaps cause extended backup runtimes too.

    Get Estimated Database Backup or Restore Time MSSQL

    When you’re waiting on a database backup or restore to complete in SQL Server, we can run the script below to get an estimated time of how long the backup has left to go –

    SQL Estimated Database Restore Time

    We have one 5GB database here currently being backed up at the time of executing the DMV script. The backup progress is at 27% and is due to complete 1 minute after the backup was initiated.

    This script will also be useful for getting the full command of the currently running SQL process on your SQL Server Instance, by removing the filter (WHERE Clause) on the query.

  • How to Get Last Backup Times for all Databases in SQL Server

    How to Get Last Backup Times for all Databases in SQL Server

    This is a post on how to get the last backup dates and times for all databases on a SQL Server Instance.

    Database backups are as important as the availability of your server. If your database gets corrupted, or there’s an accidental data deletion and you need to recover data, then we must rely on backups to get the data back. If you have no backups, you have no way to recover your lost data.

    This demo post includes the following SQL scripts to help gain database backup history information for review:
    # Get Most Recent Database Backup Info
    # Get All Database Backup Info

    If you discover a database without an associated backup you should consider reviewing the situation.


    Get Most Recent Database Backup Info

    The following script returns the most recent Full, Differential & TLog Backup times for all databases on a SQL Server Instance.

    Get Most Recent Last Backup SQL Server

    We can see from the above screenshot all databases on this SQL Server Instance have been backed up in the last 30 days. Only the demoBlog has had recent Differential and TLog Backups.

    The type column within the backupset table gives us a way of checking whether the backup was a Full, Differential or Transaction Log.


    Get All Database Backup Info

    This script is more useful if you are reviewing the history of database backups, ensuring they are being backed up on a regular schedule/interval.

    The following script will show all backups in the log, in the past 2 months.

    You can simply remove the WHERE Clause to bring back the full history if necessary.

    The above screenshot includes examples of Full, Differential & Transaction Log backups. This data can be very valuable for verifying backup chains are not broken, as well as backup sizes (including backup compression savings).

  • Drop Table if Exists in SQL Server

    Drop Table if Exists in SQL Server

    The DROP TABLE command in SQL Server will do as it suggests and drops a table. This post is to show an example of using this command, including the IF EXISTS argument.

    DROP TABLE IF EXISTS in MS SQL allows us to conditionally drop the table, meaning it does not cause an error if the database does not exist.

    DROP TABLE IF EXISTS works on SQL Server 2016 and above.
    For more information on this, as ever you should check out the Microsoft Documentation on anything and everything you do on their products.

    In the following example, I’m creating a new table followed by running the DROP TABLE IF EXISTS command. I run the DROP statement twice to show & explain the execution error part.

    # create a test table ms sql
    CREATE TABLE demoTable (r_id INT, r_name VARCHAR(100), r_description VARCHAR(200));
    
    # drop the above table
    DROP TABLE IF EXISTS T1;
    
    # drop the table again, no execution errors / script will continue
    DROP TABLE IF EXISTS T1;
    Drop Table if Exist MS SQL

    You can also get information from system tables to verify if a SQL Object exists or not. For example, having an IF statement based on a sys.tables query to check if the table exists, before running the create table statement.