Sunday, August 30, 2020

How to work with xml type using Query

Working with OPENXML in SQL Server

OPENXML is a Transact-SQL keyword that allows you to treat XML data stored in memory as if it were a relational table or view. This functionality is especially helpful when importing or transforming XML content into tabular format.

To use OPENXML, the sp_xml_preparedocument procedure is first called to parse the XML and return a handle to the document, which can then be referenced in SQL queries.

XML document

Example: Populating Tables Using OPENXML

-- Create necessary tables
CREATE TABLE Customers (
    CustomerID varchar(20) PRIMARY KEY,
    ContactName varchar(20),
    CompanyName varchar(20)
);

CREATE TABLE Orders (
    CustomerID varchar(20),
    OrderDate datetime
);

-- Declare XML and handle
DECLARE @docHandle int;
DECLARE @xmlDocument nvarchar(max);

-- Set XML data
SET @xmlDocument = N'
<ROOT>
  <Customers CustomerID="XYZAA" ContactName="Joe" CompanyName="Company1">
    <Orders CustomerID="XYZAA" OrderDate="2000-08-25T00:00:00" />
    <Orders CustomerID="XYZAA" OrderDate="2000-10-03T00:00:00" />
  </Customers>
  <Customers CustomerID="XYZBB" ContactName="Steve" CompanyName="Company2">
    No Orders yet!
  </Customers>
</ROOT>';

-- Prepare the XML document
EXEC sp_xml_preparedocument @docHandle OUTPUT, @xmlDocument;

-- Insert customers
INSERT INTO Customers
SELECT * FROM OPENXML(@docHandle, '/ROOT/Customers') WITH Customers;

-- Insert orders
INSERT INTO Orders
SELECT * FROM OPENXML(@docHandle, '//Orders') WITH Orders;

-- Query with OPENXML
SELECT * FROM OPENXML(@docHandle, '/ROOT/Customers/Orders')
  WITH (CustomerID nchar(5) '../@CustomerID', OrderDate datetime);

-- Clean up the XML handle
EXEC sp_xml_removedocument @docHandle;

Example: Using nodes() Method

SELECT 
    nref.value('(first-name/text())[1]', 'nvarchar(50)') AS FirstName,
    nref.value('(last-name/text())[1]', 'nvarchar(50)') AS LastName
FROM T
CROSS APPLY xCol.nodes('//author') AS R(nref)
WHERE nref.exist('first-name[. != "David"]') = 1;

Looping Through XML Using OPENXML()

DECLARE name_cursor CURSOR FOR 
    SELECT xCol FROM T;

OPEN name_cursor;

DECLARE @xmlVal XML;
DECLARE @idoc int;

FETCH NEXT FROM name_cursor INTO @xmlVal;

WHILE (@@FETCH_STATUS = 0)
BEGIN
    EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlVal;

    SELECT * 
    FROM OPENXML(@idoc, '//author') 
    WITH (
        FirstName varchar(50) 'first-name',
        LastName varchar(50) 'last-name'
    ) R
    WHERE R.FirstName != 'David';

    EXEC sp_xml_removedocument @idoc;

    FETCH NEXT FROM name_cursor INTO @xmlVal;
END

CLOSE name_cursor;
DEALLOCATE name_cursor;

Example XML Structure

<Customers xmlns:xsd="http://www.w3.org/2001/XMLSchema"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Customer>
       <ItemId>1001</ItemId>
       <Value>Mr Patel</Value>
   </Customer>
   <Customer>
      <ItemId>2002</ItemId>
      <Value>Mr Bhatt</Value>
   </Customer>
</Customers>

Extracting Data from XML

SELECT
    Cst.value('(ItemId)[1]', 'int') AS ItemID,
    Cst.value('(Value)[1]', 'Varchar(50)') AS CustomerName
FROM dbo.Sales.CustomerList.nodes('/Customers/Customer') AS A(Cst);

Using CROSS APPLY with XML

CREATE TABLE Sales2020 (ID int, CustomerList xml);

INSERT INTO Sales2020
SELECT 1, '
    <Customers xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <Customer>
           <ItemId>1001</ItemId>
           <Value>Mr Patel</Value>
       </Customer>
       <Customer>
          <ItemId>2</ItemId>
          <Value>Mr Bhatt</Value>
       </Customer>
    </Customers>';

SELECT
   N.C.value('ItemId[1]', 'int') AS ItemId,
   N.C.value('Value[1]', 'varchar(100)') AS Value
FROM Sales2020
CROSS APPLY CustomerList.nodes('//Customer') AS N(C);

References

How to write PowerShell script using TSQL

Executing PowerShell Scripts via T-SQL in SQL Server

In scenarios where direct access to the server is unavailable, SQL Server allows the execution of PowerShell scripts through T-SQL by utilizing the xp_cmdshell extended stored procedure. This method enables administrators to perform system-level tasks without leaving the SQL Server environment.

Steps to Execute PowerShell Scripts:

  1. Enable xp_cmdshell:
    First, enable the xp_cmdshell feature to allow the execution of operating system commands:
    sp_configure 'xp_cmdshell', 1;
    RECONFIGURE;
  2. Run PowerShell Commands:
    Execute PowerShell commands using xp_cmdshell. For example, to list all running processes:
    xp_cmdshell 'powershell.exe -command Get-Process';
    To check disk space:
    xp_cmdshell 'PowerShell.exe -command "get-diskspace ."';
    For performance counters:
    xp_cmdshell 'PowerShell.exe -noprofile -command "Get-counter -counter ''\LogicalDisk(*)\% Free Space'' | select -expand countersamples"';

Security Considerations:

  • Permissions: Ensure that only trusted users have access to xp_cmdshell due to its potential security risks.
  • Execution Policy: PowerShell's execution policy might restrict script execution. Adjust it as necessary:
    Set-ExecutionPolicy RemoteSigned;

Use Cases:

This approach is particularly useful for automating administrative tasks, monitoring system performance, and gathering system information directly from within SQL Server.

How to Reset Identity Value in SQL Server

In SQL Server, identity columns are used to automatically generate unique numeric values, commonly for primary key columns. However, situations may arise, such as after deleting records or resetting test data, where you need to reset the identity value so that new records start with a specific number again.

If you've ever deleted all the rows from a table but noticed that the identity column keeps incrementing from the last used value, this post will show you how to reset it using the DBCC CHECKIDENT command.

👉 Original post: How to Reset Identity Value

What is DBCC CHECKIDENT?

SQL Server provides the A DBCC CHECKIDENT command to manually reseed (reset) the identity value of a table. This is particularly useful after large deletions or when reloading data during development or ETL processes.

Syntax:

DBCC CHECKIDENT ('TableName', RESEED, NewSeedValue);
  • 'TableName': Your table name.
  • RESEED: Instructs SQL Server to change the identity value.
  • NewSeedValue: The number you want the next identity value to start from.

Example Scenario

Suppose you have a table called Employee With an identity column ID.

To reset the identity to start from 1 after deleting all records:

DELETE FROM Employee;
DBCC CHECKIDENT ('Employee', RESEED, 0);

⚠️ Note: If you reseed to 0, the next row inserted will receive ID = 1 (since identity starts from the seed + 1).

How to Check the Current Identity Value

To see the current identity seed without making changes:

DBCC CHECKIDENT ('Employee', NORESEED);

This will return the current seed and the next value to be used.

Important Considerations

  • TRUNCATE vs DELETE: Using TRUNCATE TABLE resets the identity automatically, but DELETE does not.
  • Existing Records: Be careful when reseeding if the table still contains rows—setting the seed too low can cause primary key violations.
  • Permissions: Running DBCC CHECKIDENT may require ALTER permissions on the table.

When Should You Reset Identity Values?

  • After deleting test or demo data in development environments.
  • During staging or ETL operations, when reloading data.
  • When maintaining a consistent identity sequence is necessary for reports or integrations.

Resetting identity values is a simple but powerful feature in SQL Server. With DBCC CHECKIDENT, you can take control over how identity values are managed in your tables.

For more details, you can refer to the following links:

Reassign the Identity of All Tables

The table has Identity Columns

Saturday, August 29, 2020

Get top total worker time queries

 Get top total worker time queries

Ever wondered which SQL queries are hogging resources on your database? This handy SQL script helps you identify the top 50 culprits based on their total worker time. It provides a quick overview of query performance, including average execution times, logical reads, and even flags queries that might benefit from a missing index!

SELECT TOP (50) DB_NAME(t.[dbid]) AS [Database Name]
 ,REPLACE(REPLACE(LEFT(t.[text], 255), CHAR(10), ''), CHAR(13), '') AS [Short Query Text]
 ,qs.total_worker_time AS [Total Worker Time]
 ,qs.min_worker_time AS [Min Worker Time]
 ,qs.total_worker_time / qs.execution_count AS [Avg Worker Time]
 ,qs.max_worker_time AS [Max Worker Time]
 ,qs.min_elapsed_time AS [Min Elapsed Time]
 ,qs.total_elapsed_time / qs.execution_count AS [Avg Elapsed Time]
 ,qs.max_elapsed_time AS [Max Elapsed Time]
 ,qs.min_logical_reads AS [Min Logical Reads]
 ,qs.total_logical_reads / qs.execution_count AS [Avg Logical Reads]
 ,qs.max_logical_reads AS [Max Logical Reads]
 ,qs.execution_count AS [Execution Count]
 ,CASE WHEN CONVERT(NVARCHAR(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%<MissingIndexes>%' THEN 1 ELSE 0 END AS [Has Missing Index]
 ,qs.creation_time AS [Creation Time]
--,t.[text] AS [Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel
FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp
ORDER BY qs.total_worker_time DESC
OPTION (RECOMPILE);

This script leverages two powerful SQL Server Dynamic Management Views (DMVs) for its insights:

Give this script a try and see what insights you can uncover about your database's performance!

Sunday, August 16, 2020

Tables without a Clustered Index (Heap)

How to List SQL Server Tables Without a Primary Key

If you're working with SQL Server databases, it's essential to know which tables lack primary keys. Having a primary key on your tables ensures that each record is uniquely identified, which helps in data integrity and query optimization. However, some tables may not have a primary key, and you might need to identify them for maintenance or optimization purposes.

Query to List Tables Without a Primary Key

The following SQL query can be used to list all the tables in a SQL Server database that do not have a primary key:


SELECT [Table] = s.[Name] + N'.' + t.[Name]
FROM [sys].tables t
INNER JOIN [sys].schemas s
    ON t.[schema_id] = s.[schema_id]
WHERE NOT EXISTS (
    SELECT 1 
    FROM [sys].indexes i
    WHERE i.[object_id] = t.[object_id]
    AND i.index_id = 1
);

Explanation of the Query

  • s.Name and t.Name: These refer to the schema and table names, respectively.
  • sys.tables: This system view holds information about the tables in the database.
  • sys.schemas: This system view contains information about the schemas.
  • sys.indexes: This view provides details about the indexes on tables. The index_id = 1 corresponds to the clustered index, which is typically created when a primary key is defined.

The query checks for the absence of a primary key by ensuring that there is no clustered index (index_id = 1) associated with the table.

Additional Resources

For further reading on SQL indexes and optimization, you can explore the following blog posts:

  1. Unused Indexes: Learn About Unused Indexes in SQL Server
  2. Over-Indexes: Understanding and Managing Over-Indexes
  3. Missing Indexes: How to Identify Missing Indexes for Better Performance

By using these resources and the provided SQL query, you can identify tables without primary keys and take appropriate actions to ensure the efficiency and integrity of your database.

Saturday, August 8, 2020

Find Server property using TSQL code

Retrieving SQL Server Information Using T-SQL

In this article, we will discuss how to retrieve information about your installed SQL Server instance using a T-SQL query that interacts with internal system objects. This query can provide various details, such as the service account, paths, configuration settings, and much more.

Query Overview

The following T-SQL query retrieves multiple configuration settings and properties from SQL Server. It covers information such as the server's version, instance details, backup paths, and various registry settings. This is useful for system administrators and those who need to audit or document SQL Server environments.

The query returns a result in two columns: one with the name of the configuration setting and the other with its value.

Query Explanation

The query starts by declaring a series of variables that will hold the registry paths and values related to SQL Server configuration.


DECLARE @HkeyLocal NVARCHAR(18),
        @ServicesRegPath NVARCHAR(34),
        @SqlServiceRegPath SYSNAME,
        @BrowserServiceRegPath SYSNAME,
        @MSSqlServerRegPath NVARCHAR(31),
        @InstanceNamesRegPath NVARCHAR(59),
        @InstanceRegPath SYSNAME,
        @SetupRegPath SYSNAME,
        @NpRegPath SYSNAME,
        @TcpRegPath SYSNAME,
        @RegPathParams SYSNAME,
        @FilestreamRegPath SYSNAME;

The paths for various registry keys related to SQL Server configuration are then set:


SELECT @HkeyLocal = N'HKEY_LOCAL_MACHINE';

-- Instance-based paths
SELECT @MSSqlServerRegPath = N'SOFTWARE\\Microsoft\\MSSQLServer';
SELECT @InstanceRegPath = @MSSqlServerRegPath + N'\\MSSQLServer';
SELECT @FilestreamRegPath = @InstanceRegPath + N'\\Filestream';
SELECT @SetupRegPath = @MSSqlServerRegPath + N'\\Setup';
SELECT @RegPathParams = @InstanceRegPath + '\\Parameters';

-- Services
SELECT @ServicesRegPath = N'SYSTEM\\CurrentControlSet\\Services';
SELECT @SqlServiceRegPath = @ServicesRegPath + N'\\MSSQLSERVER';
SELECT @BrowserServiceRegPath = @ServicesRegPath + N'\\SQLBrowser';

-- InstanceId setting
SELECT @InstanceNamesRegPath = N'SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL';

-- Network settings
SELECT @NpRegPath = @InstanceRegPath + N'\\SuperSocketNetLib\\Np';
SELECT @TcpRegPath = @InstanceRegPath + N'\\SuperSocketNetLib\\Tcp';

Fetching Configuration Details

The query then retrieves various configuration values using the xp_instance_regread extended stored procedure. Some of the configuration details include:

  • Audit level
  • Number of error logs
  • Login mode
  • Mail profile
  • Backup directory

For example, the following code fetches the audit level:


DECLARE @SmoAuditLevel INT;
EXEC master.dbo.xp_instance_regread @HkeyLocal, @InstanceRegPath, N'AuditLevel', @SmoAuditLevel OUTPUT;

File Paths and Error Logs

The query continues by retrieving file paths for the master database, error logs, and other important system directories:


DECLARE @MasterPath NVARCHAR(512),
        @LogPath NVARCHAR(512),
        @ErrorLog NVARCHAR(512),
        @ErrorLogPath NVARCHAR(512);

SELECT @MasterPath = SUBSTRING(physical_name, 1, LEN(physical_name) - CHARINDEX('\\', REVERSE(physical_name)))
FROM master.sys.database_files WHERE name = N'master';

SELECT @LogPath = SUBSTRING(physical_name, 1, LEN(physical_name) - CHARINDEX('\\', REVERSE(physical_name)))
FROM master.sys.database_files WHERE name = N'mastlog';

SELECT @ErrorLog = CAST(SERVERPROPERTY(N'errorlogfilename') AS NVARCHAR(512));
SELECT @ErrorLogPath = SUBSTRING(@ErrorLog, 1, LEN(@ErrorLog) - CHARINDEX('\\', REVERSE(@ErrorLog)));

Extracting Additional Information

The query also retrieves additional server and instance details, including the service account name, whether named pipes and TCP are enabled, and more.


DECLARE @ServiceAccount NVARCHAR(512);
EXEC master.sys.xp_instance_regread @HkeyLocal, @SqlServiceRegPath, N'ObjectName', @ServiceAccount OUTPUT;

DECLARE @NamedPipesEnabled INT;
EXEC master.dbo.xp_instance_regread @HkeyLocal, @NpRegPath, N'Enabled', @NamedPipesEnabled OUTPUT;

DECLARE @TcpEnabled INT;
EXEC master.sys.xp_instance_regread @HkeyLocal, @TcpRegPath, N'Enabled', @TcpEnabled OUTPUT;

Retrieving Server and Instance Properties

The final output includes several important properties, such as the version of SQL Server, the server collation, and whether SQL Server is clustered:


SELECT
  SERVERPROPERTY(N'ProductVersion') AS [VersionString],
  CAST(SERVERPROPERTY(N'Edition') AS SYSNAME) AS [Edition],
  CAST(SERVERPROPERTY(N'ProductLevel') AS SYSNAME) AS [ProductLevel],
  SERVERPROPERTY('Collation') AS [Collation],
  CAST(SERVERPROPERTY('IsClustered') AS BIT) AS [IsClustered];

Query Result

The query outputs a list of configuration names along with their corresponding values. Here is an example of the result structure:

  • Audit Level: 1
  • Number of Error Logs: 10
  • Login Mode: 2
  • Mail Profile: NULL
  • Backup Directory: C:\Backup

Conclusion

This T-SQL query is a valuable tool for retrieving SQL Server configuration details from system registry entries and properties. By executing this query, administrators can gain insight into the SQL Server instance’s configuration without needing to manually inspect the system or configuration files.

Availability group fail-over

Forced Manual Failover with Data Loss (2-step Process)

To force a failover with potential data loss, connect to the SQL Server instance where the secondary replica is hosted, and execute the following command:

ALTER AVAILABILITY GROUP [ag1] FORCE_FAILOVER_ALLOW_DATA_LOSS;

Once the original primary replica recovers, it will try to assume the primary role. To ensure the previous primary becomes secondary again, run the command below on that instance:

ALTER AVAILABILITY GROUP [ag1] SET (ROLE = SECONDARY);

Steps to Manually Failover Without Data Loss:

1. First, configure the target secondary replica to use SYNCHRONOUS_COMMIT mode:

ALTER AVAILABILITY GROUP [ag1]
     MODIFY REPLICA ON N''
     WITH (AVAILABILITY_MODE = SYNCHRONOUS_COMMIT);

2. To verify that active transactions are committed to the primary and at least one synchronous secondary replica, run the following query:

SELECT ag.name, drs.database_id, drs.group_id, drs.replica_id,
   drs.synchronization_state_desc, ag.sequence_number
FROM sys.dm_hadr_database_replica_states drs, sys.availability_groups ag
WHERE drs.group_id = ag.group_id;

3. Update the REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT setting to 1:

ALTER AVAILABILITY GROUP [ag1]
     SET (REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT = 1);

4. Offline the primary replica in preparation for the role change:

ALTER AVAILABILITY GROUP [ag1] OFFLINE;

5. Promote the target secondary replica to the primary role:

ALTER AVAILABILITY GROUP ag1 FORCE_FAILOVER_ALLOW_DATA_LOSS;

6. Change the role of the previous primary replica to SECONDARY. Run this on the SQL Server instance hosting the previous primary replica:

ALTER AVAILABILITY GROUP [ag1] SET (ROLE = SECONDARY);

For more information, check out this resource:

Check the Writable Copy

Additional reference: Manual SQL Server Availability Group Failover

Sunday, August 2, 2020

How to find SQL server Object dependency

How to find SQL server Object dependencies


In T-SQL, we can retrieve all dependent objects across all databases, including those from remote server linked objects. The `sql_expression_dependencies` system view contains one row for each dependency on a user-defined entity in the current database. This includes dependencies between scalar, user-defined functions and other SQL Server modules, including natively compiled ones.

CREATE TABLE #alldep (
  dbname VARCHAR(100),
  objname VARCHAR(100),
  sdbname VARCHAR(100),
  sschma VARCHAR(100),
  stable VARCHAR(100),
  sserver VARCHAR(100)
)

INSERT INTO #alldep
EXEC SP_MSFOREACHDB 'USE ? 
  SELECT db_name(), 
         OBJECT_NAME(referencing_id) AS referencing_object,
         referenced_database_name,
         referenced_schema_name,
         referenced_entity_name,
         referenced_server_name
  FROM sys.sql_expression_dependencies
  WHERE referenced_database_name IS NOT NULL
  AND is_ambiguous = 0'
SELECT * FROM #alldep
SELECT * FROM #alldep WHERE sserver <> ''

For more information on the system view `sys.sql_expression_dependencies`, check the official documentation here: Microsoft Docs

How to find SQL Server installation Date

To find the installation date of SQL Server, we need to examine the creation date of the "NT Authority\\System" login. This login is created during the SQL Server installation process.

-- Query to retrieve the server installation date
SELECT create_date 
FROM sys.server_principals 
WHERE name = 'NT AUTHORITY\\SYSTEM';
-- Alternate query to retrieve the server installation date using SID
SELECT create_date, *  
FROM sys.server_principals 
WHERE sid = 0x010100000000000512000000;
-- Query to retrieve the creation date for the "NT AUTHORITY\\NETWORK SERVICE" login
SELECT create_date 
FROM sys.server_principals 
WHERE name = N'NT AUTHORITY\\NETWORK SERVICE';

For more information, check out the following articles:

Popular Posts