LazyMouse – R package for randomly moving mouse cursor

New R Package called LazyMouse with single function for randomly moving mouse cursor in your favorite R IDE.

For every R developer, R data scientists and all those everyday R users, that also need a break and do not want the computer to go into sleep mode.

To install the package, use:

install.packages("remotes")
remotes::install_github("tomaztk/LazyMouse")

The complete installation (with all dependencies and packages preinstalled), can be found in the details on my github repository LazyMouse and the file: Install_package.r.

For better convenience have RTools installed as well in your working environment and have Rcpp, remotes and devtools.

Happy R coding

Tagged with: , ,
Posted in R, Useless R functions

Advent of 2025, Day 24 – SQL Server 2025 – Documentation and learning materials

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION
  18. Dec 18: Microsoft SQL Server 2025 – Optimized locking
  19. Dec 19: Microsoft SQL Server 2025 – New T-SQL functions – CURRENT_DATE
  20. Dec 20: Microsoft SQL Server 2025 – Change Event Streaming
  21. Dec 21: Microsoft SQL Server 2025 – Change Event Streaming – part 2
  22. Dec 22: Microsoft SQL Server 2025 – T-SQL Features – UNISTR()
  23. Dec 23: Microsoft SQL Server 2025 – T-SQL Features – String concatenation with || and compound assignment ||=

Microsoft website for SQL Server: https://www.microsoft.com/en-us/sql-server is always a good way to start. But if you would like to start more in depth documentation here is Microsoft documentation:

General Youtube videos:

General Github repositories:

Books:

  • Bob Wards’s SQL Server 2025 book
  • And you can always grab a book by Microsoft, Apress, O’Reilly, Packt, and many others. And you can always grab a book by the following authors: Bob Ward, Itzik Ben-Gan, Dejan Sarka, Pedro Lopes, Grant Fritchey, and many many others.)

Websites / Blogs:

There are also Udemy, Coursera, edX, Harward and many other courses that covers a lot different topics from installation, to database administration, to development, to analytics, services and many other topics.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

With this blogpost we end the series of Advent of blog 2025! I wish you all Merry Xmas and Happy New Year 2026!

Tagged with: , , , , , , ,
Posted in SQL Server, Uncategorized

Advent of 2025, Day 23 – SQL Server 2025 – T-SQL Features – String concatenation with || and compound assignment ||=

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION
  18. Dec 18: Microsoft SQL Server 2025 – Optimized locking
  19. Dec 19: Microsoft SQL Server 2025 – New T-SQL functions – CURRENT_DATE
  20. Dec 20: Microsoft SQL Server 2025 – Change Event Streaming
  21. Dec 21: Microsoft SQL Server 2025 – Change Event Streaming – part 2
  22. Dec 22: Microsoft SQL Server 2025 – T-SQL Features – UNISTR()

Two new features are available in SQL Server 2025 for string operations; both for string concatenation.

|| Operator

The string operator || concatenates two (or more) strings into a single expression. This operator follows the ANSI SQL Standard for concatenating strings. It is similar to CONCAT() function.

SELECT CONCAT('Hello' , ', ' , 'There!') as three_strings_concat
UNION ALL
SELECT 'Hello' || ', ' || 'There!'

We will test how the NULL and empty string behaves and what are the possible concatenations.

DROP TABLE IF EXISTS test
CREATE TABLE test (
tex1 VARCHAR(100)
,tex2 VARBINARY
,tex3 VARCHAR(10))


INSERT INTO test values
(NULL, NULL, NULL), ('Hello', NULL, ''), ('',0xA5, '$"#$"#$"'), (NULL, NULL, '')

SELECT
tex1
,tex2
,tex3
-- ,tex1 || tex2 -- will return error - can not concat varchar and varbinary
,tex1 || tex3 -- concat NULL and empty string will return NULL!
FROM test

We will see that the || operator will produce:

  1. NULL value when concatenating NULL and empty string,
  2. NULL with NULL will not return error but will concatenate to NULL
  3. VARCHAR and VARBINARY are incompatible in the concat operator.

||= compound concatenation assignment

While going through documentation, I found that this little amazing nugget was also shipped with SQL Server 2025.

The ||= concatenation with compound assignment operator can be used to concatenate the string using expression and assigning the results expression to the variable.

It is similar behavior to the Append functionality with many programming languages

DECLARE @v1 varchar(20) = 'Hello'
SELECT @v1 as v1
SET @v1 ||= ' There!';
SELECT @v1 as v2

This is an amazing operator for working with intermediate results, loops or any kind of batch logic that you need to implement in T-SQL. But be aware with NULL


DECLARE @v1 varchar(20) = NULL
SET @v1 ||= ' There!';
SELECT @v1 

DECLARE @v2 varchar(20) = 'Hello, There!'
SET @v2 ||= NULL;
SELECT @v2

Since both results will yield NULL!

Tomorrow we will check the available documentation and learning paths for SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , , , ,
Posted in SQL Server, Uncategorized

Advent of 2025, Day 22 – SQL Server 2025 – T-SQL Features – UNISTR()

n this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION
  18. Dec 18: Microsoft SQL Server 2025 – Optimized locking
  19. Dec 19: Microsoft SQL Server 2025 – New T-SQL functions – CURRENT_DATE
  20. Dec 20: Microsoft SQL Server 2025 – Change Event Streaming
  21. Dec 21: Microsoft SQL Server 2025 – Change Event Streaming – part 2

UNISTR() function is a new T-SQL function in SQL Server 2025. It will help you with unicode string literals (e.g.: special characters, emoji, special language alphabets and others) by letting you specify the unicode encoding value of characters in the string.

Difference between NCHAR and UNISTR is that latter will provide more flexibility and ways of handling multiple unicode characters and even escape sequences. You can also define a custom escape character to perform the necessary conversion of Unicode values into a string character set.

We can use the emoji in export (link to code of the emojis: link)

And for example the sleeping face is:

U+1F634😴😴sleeping face

I can also get this into SQL Server, by copy/paste the code “U+1F634” and change it to “\+01F634”

SELECT UNISTR(N'Sleepy face: \+01F634')

As we can see the UNISTR removes the need for complex string concatenation.

We can also use it for escape characters that will not be included. Think for example we would like to say Thank you and add Japanese writing (arigatou gozaimasu but with ありがとう ございます) with literal unicode “\u3042\u308a\u304c\u3068\u3046\u0020\u3054\u3056\u3044\u307e\u3059”. I have converted Japanese to Unicode using this website.

And we can test the query with UNISTR function.

SELECT N'ありがとう ございます' as TY_alone
SELECT 'Thank you' AS T_Y
SELECT 'Thank you ' + N'ありがとう ございます' as TY_mixed
SELECT UNISTR(N'Thank you \3042\308a\304c\3068\3046\0020\3054\3056\3044\307e\3059', '\') as Thank_you

Tomorrow we will continue to explore the new T-SQL functions in SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , ,
Posted in SQL Server

Advent of 2025, Day 21 – SQL Server 2025 – Change Event Streaming – part 2

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION
  18. Dec 18: Microsoft SQL Server 2025 – Optimized locking
  19. Dec 19: Microsoft SQL Server 2025 – New T-SQL functions – CURRENT_DATE
  20. Dec 20: Microsoft SQL Server 2025 – Change Event Streaming

We have looked into the settings of SQL server and generating SAS token. And now we will need to set the needed Azure services.

Create Event Hub in Azure Portal

In Portal create a new Event hub namespace.

Within this namespace, we will add an event hub. In the namespace, create an event hub (click on “+ Event hub”):

And specify the event hub:

Once we have event hub created, we need to add the SAS token and specify the policy. In the namespace we will go to settings > Shared access policies and click on “+ Add” to add new policy:

And give the policy name and we selected the Manage access!

Setup the SQL Server 2025

We will create a database, get the credentials, SAS token (we have generated SAS token using Powershell script in previous blogpost) and enable CES (!) As the time of writing this blogpost, the SET PREVIEW_FEATURES = ON for database scoped configuration had to be set to ON.

USE master
GO
 
CREATE DATABASE db_22_CES;
GO
 
USE db_22_CES
GO
 

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'H@rd2Gue$$P@$$w0rd'

CREATE DATABASE SCOPED CREDENTIAL SqlCesCredential
WITH
  IDENTITY = 'SHARED ACCESS SIGNATURE',
  SECRET = '*****token_from_Powershell_Script********' 

And a snip for generating SAS token using Powershell:

And now we create tables where the CES will be getting the changes:


-- Create some demo tables
CREATE TABLE dbo.Customer (
  CustomerId    int IDENTITY PRIMARY KEY,
  CustomerName  varchar(50),
  CustomerCity   varchar(20)
);
GO
 

INSERT INTO dbo.Customer (CustomerName,   CustomerCity) VALUES
  ('Awesome bikes','Manila'),
  ('Fixed Gear bikes Co.','Capetown'),
  ('Red gears', 'London');
  GO

 
CREATE TABLE dbo.Products (
  ProductId     int IDENTITY PRIMARY KEY,
  ProductName          varchar(80),
  UnitPrice     decimal(8, 2)
);
GO
 
 
INSERT INTO dbo.Products
  (ProductName,  UnitPrice) VALUES
  ('Cinelli Verduro 1024', 3899.99),
  ('Leader A 524', 1996.95);
  GO
 
 
-- procedure to add new rows to table
CREATE PROCEDURE dbo.AddProduct
  @ProductName varchar(80)
  ,@UnitPrice decimal(8,2)
AS
BEGIN
  INSERT INTO dbo.Products(ProductName,  UnitPrice)
  VALUES (@ProductName, @UnitPrice)

END
GO

Once we have tables in place, we will enable the CES:

 -- Make sure to have preview feature enabled (for your database "db_22_CES")
ALTER DATABASE SCOPED CONFIGURATION SET PREVIEW_FEATURES = ON;

EXEC sys.sp_enable_event_stream
-- OK

SELECT is_event_stream_enabled, * FROM sys.databases  WHERE is_event_stream_enabled = 1

Create event stream group and we register each of the table:

  -- Create event stream group

  EXEC sys.sp_create_event_stream_group
  @stream_group_name      = 'SqlCesGroup',
  @destination_location   = 'ces-demo-sqlserver2025-namespace.servicebus.windows.net/ces-hub',
  @destination_credential = SqlCesCredential2,
  @destination_type       = 'ces-demo-evhub'

EXEC sys.sp_add_object_to_event_stream_group
  @stream_group_name = 'SqlCesGroup',
  @object_name = 'dbo.Customer',
  @include_old_values = 1,    
  @include_all_columns = 1      
 
EXEC sys.sp_add_object_to_event_stream_group
  @stream_group_name = 'SqlCesGroup',
  @object_name = 'dbo.Products',
  @include_old_values = 1,      
  @include_all_columns = 0      


-- verify CES on tables:
EXEC sp_help_change_feed_table @source_schema = 'dbo', @source_name = 'Customer'
EXEC sp_help_change_feed_table @source_schema = 'dbo', @source_name = 'Products'

And finally, we are ready to do some inserts or updates or deletes or any change (DDL, DML) on our tables.

All the changes are present in the event hub:

For the purpose of storing the logs, we create an Stream Analytics job to hold and store the results. We have the results stored the logs into the Azure Data lake ( ADLS in parquet format).

Tomorrow we will continue to explore the new T-SQL functions in SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , , , , ,
Posted in SQL Server, Uncategorized

Advent of 2025, Day 20 – SQL Server 2025 – Change Event Streaming

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION
  18. Dec 18: Microsoft SQL Server 2025 – Optimized locking
  19. Dec 19: Microsoft SQL Server 2025 – New T-SQL functions – CURRENT_DATE

Change event streaming (CES) is data integration capability that streams SQL Server data changes directly into Azure Event hubs. It captures and publishes incremental changes of data to an Azure Event Hubs destination in almost near real-time. Captured changes are insert, updates and deleted (DML) and are sent to Azure Event hubs as a serialized JSON (CloudEvent) and streamed to Azure event hub.

CES can be used for multiple different use-cases, like monitoring, auditing, event-driven system on top of your on-prem database with minimal overhead and changes to database, for synchronising data across systems (platforms, on-prem and cloud solutions, etc.) and many more.

We will cover scenario, where SQL Server 2025 will be installed on prem and we will use Azure event hub. Before we start, we will need to do some of the configurations.

Here are differences between change tracking (CT), Change Data Capture (CDC) and Change Event Streaming (CES):

Configure your SQL Server 2025

We will need to:
– a login in the db_owner role or that has CONTROL_DATABASE permission for the database where you intend to enable CES,
– enable the preview feature database scoped configuration,
– prepare Powershell modules for working with Azure and Azure eventhubs (Az, Az.EventHub)

Run the Powershell scripts for installation:

Install-Module -Name Az -AllowClobber -Scope CurrentUser -Repository PSGallery -Force
Install-Module -Name Az.EventHub -Scope CurrentUser -Force

We will need to create a SAS token for authorization and connection to Azure. Replace must be the ResourceName, Namespace, Eventhub, PolicyName, and SubscriptionID.

function Generate-SasToken {
$subscriptionId = "<Azure-Subscription-ID>"
$resourceGroupName = "<Resource-group-name>"
$namespaceName = "<Azure-Event-Hub-Namespace-name>"
$eventHubName = "<Azure-Event-Hubs-instance-name>"
$policyName = "<Policy-name>"
$tokenExpireInDays = "<number-of-days-token-will-be-valid>"

# Modifying the rest of the script is not necessary.

# Login to Azure and set Azure Subscription.
Connect-AzAccount

# Get current context and check subscription
$currentContext = Get-AzContext
if ($currentContext.Subscription.Id -ne $subscriptionId) {
    Write-Host "Current subscription is $($currentContext.Subscription.Id), switching to $subscriptionId..."
    Set-AzContext -SubscriptionId $subscriptionId | Out-Null
} else {
    Write-Host "Already using subscription $subscriptionId."
}

# Try to get the authorization policy (it should have Send rights)
$rights = @("Send")
$policy = Get-AzEventHubAuthorizationRule -ResourceGroupName $resourceGroupName -NamespaceName $namespaceName -EventHubName $eventHubName -AuthorizationRuleName $policyName -ErrorAction SilentlyContinue

# If the policy does not exist, create it
if (-not $policy) {
    Write-Output "Policy '$policyName' does not exist. Creating it now..."

# Create a new policy with the Manage, Send and Listen rights
    $policy = New-AzEventHubAuthorizationRule -ResourceGroupName $resourceGroupName -NamespaceName $namespaceName -EventHubName $eventHubName -AuthorizationRuleName $policyName -Rights $rights
    if (-not $policy) {
        throw "Error. Policy was not created."
    }
    Write-Output "Policy '$policyName' created successfully."
} else {
    Write-Output "Policy '$policyName' already exists."
}

if ("Send" -in $policy.Rights) {
    Write-Host "Authorization rule has required right: Send."
} else {
    throw "Authorization rule is missing Send right."
}

$keys = Get-AzEventHubKey -ResourceGroupName $resourceGroupName -NamespaceName $namespaceName -EventHubName $eventHubName -AuthorizationRuleName $policyName

if (-not $keys) {
    throw "Could not obtain Azure Event Hub Key. Script failed and will end now."
}
if (-not $keys.PrimaryKey) {
    throw "Could not obtain Primary Key. Script failed and will end now."
}

# Get the Primary Key of the Shared Access Policy
$primaryKey = ($keys.PrimaryKey)
Write-Host $primaryKey

## Check that the primary key is not empty.

# Define a function to create a SAS token (similar to the C# code provided)
function Create-SasToken {
    param (
        [string]$resourceUri, [string]$keyName, [string]$key
    )

$sinceEpoch = [datetime]::UtcNow - [datetime]"1970-01-01"
    $expiry = [int]$sinceEpoch.TotalSeconds + ((60 * 60 * 24) * [int]$tokenExpireInDays) # seconds since Unix epoch
    $stringToSign = [System.Web.HttpUtility]::UrlEncode($resourceUri) + "`n" + $expiry
    $hmac = New-Object System.Security.Cryptography.HMACSHA256
    $hmac.Key = [Text.Encoding]::UTF8.GetBytes($key)
    $signature = [Convert]::ToBase64String($hmac.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)))
    $sasToken = "SharedAccessSignature sr=$([System.Web.HttpUtility]::UrlEncode($resourceUri))&sig=$([System.Web.HttpUtility]::UrlEncode($signature))&se=$expiry&skn=$keyName"
    return $sasToken
}

# Construct the resource URI for the SAS token
$resourceUri = "https://$namespaceName.servicebus.windows.net/$eventHubName"

# Generate the SAS token using the primary key from the new policy
$sasToken = Create-SasToken -resourceUri $resourceUri -keyName $policyName -key $primaryKey

# Output the SAS token
Write-Output @"
-- Generated SAS Token --
$sasToken
-- End of generated SAS Token --
"@
}

Generate-SasToken

Available on Microsoft learn website.

With a SAS token available, we will configure the SQL Server:

USE db_20_CES;
GO

-- Create the Master Key with a password.
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<Password>';

CREATE DATABASE SCOPED CREDENTIAL <CredentialName>
    WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
    SECRET = 'xxxxxxxxxxxx' -- Be sure to copy the entire token. The SAS token starts with "SharedAccessSignature sr="

EXEC sys.sp_enable_event_stream

EXEC sys.sp_create_event_stream_group
    @stream_group_name =      N'<EventStreamGroupName>',
    @destination_type =       N'AzureEventHubsAmqp',
    @destination_location =   N'<AzureEventHubsHostName>/<EventHubsInstance>',
    @destination_credential = <CredentialName>,
    @max_message_size_kb =    <MaxMessageSize>,
    @partition_key_scheme =   N'<PartitionKeyScheme>'

EXEC sys.sp_add_object_to_event_stream_group
    N'<EventStreamGroupName>',
    N'<SchemaName>.<TableName>'

Tomorrow we will continue to explore Change event streaming and setup everything in Azure .

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , , ,
Posted in SQL Server, Uncategorized

Advent of 2025, Day 19 – SQL Server 2025 – New T-SQL functions – CURRENT_DATE

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION
  18. Dec 18: Microsoft SQL Server 2025 – Optimized locking

This function returns the current database system date as a date value, without the database time and time zone offset. CURRENT_DATE derives this value from the underlying operating system on the Database Engine runs. This function is eqvivalent to CAST(GETDATE() AS DATE).

Let’s check the precisions to see, where we will lose the precision based on the system date/datetime functions.

SELECT CURRENT_DATE;
GO

-- precisions
SELECT 
		 SYSDATETIME() AS Sys_datetime
		,SYSDATETIMEOFFSET() AS sys_DatetimeOffset
		,SYSUTCDATETIME() AS SysUTC_Datetime
		,CURRENT_TIMESTAMP AS Curr_Timestamp
		,GETDATE() AS Get_date
		,GETUTCDATE() as Get_UTCDate
		,CURRENT_DATE AS current_d
		,CAST(GETDATE() AS DATE) as current_d_cast

Function current_date can be used also as default when creating a table:

DROP TABLE IF EXISTS dbo.TEST;
GO

CREATE TABLE dbo.test
(ID INT IDENTITY(1,1) NOT NULL
,tt CHAR(10) NULL
,dd DATE NOT NULL DEFAULT CURRENT_DATE
,ddtt SMALLDATETIME NOT NULL DEFAULT DATEADD(DAY,1,CURRENT_DATE)
)

INSERT INTO dbo.test (tt, dd)
SELECT 'aaa','2025-12-19' UNION ALL
SELECT 'bbb','2025-12-20 05:26:46.947' UNION ALL
SELECT 'ccc',GETDATE() UNION ALL
SELECT 'ddd',DATEADD(DAY, 8,CAST(GETDATE() AS DATE)) union all
select 'eee',CURRENT_TIMESTAMP 

SELECT * FROM dbo.TEST

where current date and time (of making this test was: 19th December 2025, 06.20 AM CET).

Tomorrow we will look into the new CES feature in SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , ,
Posted in SQL Server

Advent of 2025, Day 18 – SQL Server 2025 – Optimized locking

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)
  17. Dec 17: Microsoft SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION

Optimized locking is a new feature in SQL Server 2025. It helps to reduce lock memory as very few locks are held even for large transactions. In addition, optimized locking avoids lock escalations and can avoid certain types of deadlocks. This allows more concurrent access to the table.

Optimized locking is composed of two primary components:
transaction ID (TID) locking and
lock after qualification (LAQ).

The logic behind is that

  • Without optimized locking, updating 1,000 rows in a table might require 1,000 exclusive (X) row locks held until the end of the transaction.
  • With optimized locking, updating 1,000 rows in a table might require 1,000 X row locks but each lock is released as soon as each row is updated, and only one X TID lock is held until the end of the transaction. Because locks are released quickly, lock memory usage is reduced and lock escalation is much less likely to occur, improving workload concurrency.

Check for optimized locking

First we need to check if the optimized locking is set to on:

CREATE DATABASE db_18_OptimizedLocking;
GO

USE db_18_OptimizedLocking;
GO

SELECT database_id,
       name,
       is_accelerated_database_recovery_on,
       is_read_committed_snapshot_on,
       is_optimized_locking_on
FROM sys.databases
WHERE name = DB_NAME();

And it is turned off! It si enabled per database and is it by default disabled!

Let’s prepare the sample data:

DROP TABLE IF EXISTS dbo.TestTable
GO
CREATE TABLE dbo.TestTable
(
ID INT NOT NULL,
Val INT
);

INSERT INTO dbo.TestTable (ID, Val) 
VALUES (1,10),(2,20),(3,30);
GO

SELECT * FROM dbo.TestTable
GO

Test without optimized locking

We will open three NEW queries and in each new file, we will copy / paste two concurrent update statements, the first will change the row with the ID = 1 (session 1) and the second one tries to change the row with the ID = 2 (session 2). In the last one (right pane – session 3) we placed the statement to show you the locks.


The second statement is blocked, because it can not acquire the necessary Update Lock which is needed to update the row:

-- file 1 (Session 1)
USE db_18_OptimizedLocking;
go

BEGIN transaction
UPDATE TestTable
SET val = val + 10
where id = 1

-- COMMIT TRANSACTION
ROLLBACK;
GO


-- file 2 (Session 2)
USE db_18_OptimizedLocking;
go

begin transaction
update TestTable
SET  val = val + 30
WHERE id = 2

-- COMMIT TRANSACTION
ROLLBACK
GO


-- file 3 (Session 3)
select 
    resource_type,
    resource_database_id,
    resource_associated_entity_id,
   -- resource_description,
    request_mode,
    request_session_id,
    request_status

 from sys.dm_tran_locks;
GO

We see the lock

Test with optimized locking on (ADR on and RSCI off)

Now we will enable the optimized locking by enabling ADR before hand.

USE [master]
GO
ALTER DATABASE [db_18_OptimizedLocking] SET ACCELERATED_DATABASE_RECOVERY = ON;
GO
ALTER DATABASE [db_18_OptimizedLocking] SET OPTIMIZED_LOCKING = ON;
GO

SELECT DATABASEPROPERTYEX(DB_NAME(), 'IsOptimizedLockingOn') AS IsOptimizedLockingOn
GO

We get the enabled everything except RSCI (which is off).

And we will repeat the same test again:

And we see the new resource type of request mode = X was granted

TEst with optimized locking on

Test with optimized locking on (ADR on and RSCI on!)

We will turn on the RSCI:

ALTER DATABASE [db_18_OptimizedLocking] 
SET READ_COMMITTED_SNAPSHOT ON;
GO

With all the features turned on:

And with the READ COMMITTED SNAPSHOT ON we get the resource type XACT with the request mode = X, which is update immediatelly and ready for new updates, without any locks (both updates are executed)

and for both updates we get granted transaction lock (resource_type = XACT and request_mode = X):

When Optimized Locking is enabled, the query in session 2 is not blocked because update (U) locks are not acquired. Thanks to the Transactions ID (TID) and Lock After Qualifications (LAQ), Optimized locking reduces the memory consumption and reduced locks between concurrent transactions.

Tomorrow we will look into the new CURRENT_DATE in SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , , , ,
Posted in SQL Server, Uncategorized

Advent of 2025, Day 17 – SQL Server 2025 – Query hint ABORT_QUERY_EXECUTION

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings
  16. Dec 16: Microsoft SQL Server 2025 – Optional parameter plan optimization (OPPO)

New query hint, ABORT_QUERY_EXECUTION is intended to be used as a Query Store hint to let
administrators block future execution of known problematic queries, for example non-essential queries causing high resource consumption and affecting application workloads.

PREPARATION

We will need to have Query store enabled.

USE master;
GO
ALTER DATABASE [db_16_IQP]
SET QUERY_STORE = ON;
GO
 
ALTER DATABASE [db_16_IQP] 
SET QUERY_STORE CLEAR;
GO

ABORT QUERY EXECUTION

Once we have query store enabled for the database we will be running query against, we just need a query 🙂 We are using the “db_16_IQP” database, we have created in previos blog post.

USE [db_16_IQP];
GO

WITH LargeDataSet AS (
    SELECT 
    O1.productID as P1
    ,O1.Quantity as Q1
    ,O2.ProductID as P2
    ,O2.Quantity as Q2
    ,O2.CreatedDate AS CDate
      FROM  [dbo].[OrderLines] as O1
      CROSS JOIN  [dbo].[OrderLines] as O2
    
)
SELECT 
* 
FROM
    LargeDataSet  AS LDS
WHERE LDS.Q1 < 2 
  AND LDS.P2 > 4997 
  AND LDS.Q2 = 1 
  AND LDS.P1 < 6;
GO

The query execution takes cca 6 seconds to complete and returns 599.172 rows.

And now we need to find a plan and query ID in Query store:

SELECT 
    qsqt.query_sql_text,
    qsp.plan_id,
    qsp.query_id,
    rs.avg_duration,
    rs.count_executions
FROM 
    sys.query_store_query_text AS qsqt
JOIN 
    sys.query_store_query AS qsq
    ON qsqt.query_text_id = qsq.query_text_id
JOIN 
    sys.query_store_plan AS qsp
    ON qsq.query_id = qsp.query_id
JOIN 
    sys.query_store_runtime_stats AS rs
    ON qsp.plan_id = rs.plan_id
GROUP BY qsqt.query_sql_text
                    , qsp.plan_id
                    , qsp.query_id
                    , rs.avg_duration
                    , rs.count_executions
ORDER BY 
    rs.avg_duration DESC;
GO

And since this is the only query executed, we can see from query store:

And now we will apply the Abort query execution hint for this query_id

USE [db_16_IQP];
GO
EXEC sys.sp_query_store_set_hints
 @query_id = 1,
 @query_hints = N'OPTION (USE HINT (''ABORT_QUERY_EXECUTION''))';
GO

Repeat and rerun the previous query again:

The error message is clear:

Msg 8778, Level 16, State 1, Line 95
Query execution has been aborted because the ABORT_QUERY_EXECUTION hint was specified.

Running the statistics from query store again:

SELECT 
    qsqt.query_sql_text,
    qsp.plan_id,
    qsp.query_id,
    rs.avg_duration,
    rs.count_executions
FROM 
    sys.query_store_query_text AS qsqt
JOIN 
    sys.query_store_query AS qsq
    ON qsqt.query_text_id = qsq.query_text_id
JOIN 
    sys.query_store_plan AS qsp
    ON qsq.query_id = qsp.query_id
JOIN 
    sys.query_store_runtime_stats AS rs
    ON qsp.plan_id = rs.plan_id
GROUP BY qsqt.query_sql_text, qsp.plan_id, qsp.query_id, rs.avg_duration, rs.count_executions
ORDER BY 
    plan_id asc
GO

we see that for the same query_id (=1) we get different durations; the 364 milliseconds is the second run, when the query execution was aborted.

Checking the query store hints, we will see that the query hint was inplace.

SELECT  qsh.query_id
       ,q.query_hash
       ,qt.query_sql_text
       ,qsh.query_hint_text
FROM sys.query_store_query_hints AS qsh
INNER JOIN sys.query_store_query AS q
ON qsh.query_id = q.query_id
INNER JOIN sys.query_store_query_text AS qt
ON q.query_text_id = qt.query_text_id
WHERE UPPER(qsh.query_hint_text) LIKE '%ABORT[_]QUERY[_]EXECUTION%'

Tomorrow we will look into optimized locking in SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , , , , , ,
Posted in SQL Server, Uncategorized

Advent of 2025, Day 16 – SQL Server 2025 – Optional parameter plan optimization (OPPO)

In this Microsoft SQL Server 2025 series:

  1. Dec 01: Microsoft SQL Server 2025 – Introduction and installation
  2. Dec 02: Microsoft SQL Server 2025 – New T-SQL functions – native JSON data type and some functions
  3. Dec 03: Microsoft SQL Server 2025 – New T-SQL functions – JSON Index
  4. Dec 04: Microsoft SQL Server 2025 – New T-SQL functions – Product()
  5. Dec 05: Microsoft SQL Server 2025 – New T-SQL functions – BASE64_ENCODE() and BASE64_DECODE()
  6. Dec 06: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_LIKE()
  7. Dec 07: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_SUBSTR() and REGEXP_REPLACE()
  8. Dec 08: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_INSTR() and REGEXP_COUNT()
  9. Dec 09: Microsoft SQL Server 2025 – New T-SQL functions – REGEXP_MATCHES() and REGEXP_SPLIT_TO_TABLE()
  10. Dec 10: Microsoft SQL Server 2025 – External REST endpoint invocation
  11. Dec 11: Microsoft SQL Server 2025 – External REST endpoint invocation using LLM
  12. Dec 12: Microsoft SQL Server 2025 – New vector data type and Vector functions
  13. Dec 13: Microsoft SQL Server 2025 – Vector functions
  14. Dec 14: Microsoft SQL Server 2025 – Vector arrays or embeddings with function AI_GENERATE_EMBEDDINGS
  15. Dec 15: Microsoft SQL Server 2025 – T-SQL functions for AI External_Models, Chunks and Embeddings

Part of new features in IQP (Intelligent query processing) is also OPPO – Optional parameter plan optimization – which refers to a specific variation of the parameter-sensitive plan (PSP) or Parameter Sensitive Plan Optimization (PSPO) problem in which the sensitive, parameter value that exists during query execution, controls whether we need to perform a seek into or scan a table. It is part of mitigating the parameter sniffing problem.

This is usually done by WHERE clause using the (column1 = @param1 OR @param1 IS NULL), where the seek plan might not be possible with NULLs and algebrizer – regardless of index on column1 – would chose table scan (over table seek).

Query hinting techniques, like OPTIMIZE FOR, might not be useful for this type of PSP problem because there isn’t currently an operator that dynamically changes an index seek into a scan during execution. This kind of seek->scan combination at runtime might also not be effective, because the cardinality estimates on top of that operator would likely be inaccurate.

The result is inefficient plan choices and excessive memory grants for more complex queries with similar query patterns.

Adaptive plan optimization (or a “multiplan”) is feature used with OPPO that will cover the dynamic search capabilities.

Preparations

Since OPTIONAL_PARAMETER_OPTIMIZATION is enabled by default (with SQL Server 2025; database compatibility_level = 170), we will need to turn it of for the test. In addition, I have created a new database with a table full of random data. To make test even more fun, I have added the index.

USE MASTER;
GO

CREATE DATABASE db_16_IQP;
GO

USE db_16_IQP;
GO

Use db_16_IQP
GO

-- IS enabled by default; for test, we will turn it off and then on
ALTER DATABASE SCOPED CONFIGURATION SET OPTIONAL_PARAMETER_OPTIMIZATION = OFF;
GO

DROP TABLE IF EXISTS OrderLines;
GO

CREATE TABLE OrderLines
(
     OrderLineId  int IDENTITY(1,1) PRIMARY KEY
    ,ProductId    int NOT NULL
    ,Quantity     int NOT NULL
    ,Price        money NOT NULL
    ,CreatedDate  datetime2 NOT NULL DEFAULT sysutcdatetime()
);

-- Get some sample data
INSERT INTO OrderLines (ProductId, Quantity, Price)
SELECT TOP (5000000)
       ABS(CHECKSUM(NEWID())) % 5000 + 1,
       1 + ABS(CHECKSUM(NEWID())) % 5,
       10.00 + ABS(CHECKSUM(NEWID())) % 100
FROM sys.all_objects AS a 
 CROSS JOIN sys.all_objects AS b;
GO
-- (5000000 rows affected)


CREATE INDEX IX_Product On dbo.OrderLines(ProductId)
WITH (Data_Compression = Page)
GO

And we create a procedure with WHERE clause using (column1 = @param1 OR @param1 IS NULL):

CREATE OR ALTER PROCEDURE dbo.GetOrderLines
    @ProductId int = NULL
AS
BEGIN
    SELECT *
    FROM OrderLines
    WHERE (@ProductId IS NULL OR ProductId = @ProductId);
END;
GO

The Test

Now, for the sanity, let’s also clean all the cache:

DBCC FREEPROCCACHE;
GO

And now we will be using actual execution plan to observe the behaviour of memory grants and using scans over seeks.

-- with product id + check exec plan
EXECUTE GetOrderLines @ProductId=4096;
GO

And now the same procedure without the product parameter (NULL):

-- with no product ID + exec
EXECUTE GetOrderLines;
GO

Executing the procedure with different productID parameter

-- with  product ID + check exec plan again
EXECUTE GetOrderLines @ProductId=19;
GO

Yields similar execution plan and upon checking the SQL Server Query optimizer selected the best exection plan for a query, reusing the if possible but Query store reveals that after 3 runs (ProductID = 4016, NULL and 19) I get two execution plans

with query:

-- run this only for cleaning purposes!
ALTER DATABASE db_16_IQP SET QUERY_STORE CLEAR;
GO

SELECT
    p.query_id,
    p.plan_id,
    p.last_force_failure_reason_desc,
    p.force_failure_count,
    p.last_compile_start_time,
    p.last_execution_time,
    p.*,
    q.last_bind_duration,
    q.query_parameterization_type_desc,
    q.context_settings_id,
    c.set_options,
    c.STATUS
    ,t.*
FROM sys.query_store_plan p
INNER JOIN sys.query_store_query q
    ON p.query_id = q.query_id
INNER JOIN sys.query_context_settings c
    ON c.context_settings_id = q.context_settings_id
LEFT JOIN sys.query_store_query_text t
    ON q.query_text_id = t.query_text_id;
GO

Now, we will enable OPTIONAL_PARAMETER_OPTIMIZATION=ON;

Use db_16_IQP
GO

-- IS enabled by default; for test, we will turn it off and then on
ALTER DATABASE SCOPED CONFIGURATION SET OPTIONAL_PARAMETER_OPTIMIZATION = ON;
GO

And run the clean cache and the same procedure:

DBCC FREEPROCCACHE;
GO

-- with product id + check exec plan
EXECUTE GetOrderLines @ProductId=4096;
GO

And we get the execution plan using SEEK (instead of SCAN) and the query is now altered with OPTION per plan with optional predicate.

/*
This query text was retrieved from showplan XML, and may be truncated.
*/

SELECT *
    FROM OrderLines
    WHERE (@ProductId IS NULL OR ProductId = @ProductId) 

option (PLAN PER VALUE(ObjectID = 1269579561, QueryVariantID = 1, optional_predicate(@ProductId IS NULL)))

The Query store hold the variant plan, that contains information about the parent-child relationships between the original parameterized queries (also known as parent queries), dispatcher plans, and their child query variants.

And running the procedure with NULL parameter again (now that we have OPPO turned on):

-- with no product ID + exec
EXECUTE GetOrderLines;
GO

-- with  product ID + check exec plan again
EXECUTE GetOrderLines @ProductId=19;
GO

EXECUTE GetOrderLines @ProductId=574;
GO

Execution plans are reused and regardless of the values.

Results would not always be good if tested on two or more optional parameters – check the below example:

-- the magic procedure
CREATE OR ALTER PROCEDURE dbo.GetOrderLines2
     @ProductId int = NULL
    ,@QuantityP int = NULL
AS
BEGIN
    SELECT *
    FROM OrderLines
    WHERE 
       (@ProductId IS NULL OR ProductId = @ProductId) 
    AND
       (@QuantityP IS NULL or Price = @QuantityP )

END;
GO

This would yield different performance depending on which parameters go into cache first. And OPPO is still not handling two (or more) optional parameters, but works perfectly using best execution plan – goes both for OPPO and PSPO.

For the performances I used the typical SET STATISTICS IO ON / OFF wrapped around the queries.

Tomorrow we will look into other new IQP additions for SQL Server 2025.

As always, the code is available at my Github: https://github.com/tomaztk/SQLServer2025

Happy coding!

Tagged with: , , , , , , , ,
Posted in SQL Server, Uncategorized
Follow TomazTsql on WordPress.com
Programs I Use: SQL Search
Programs I Use: R Studio
Programs I Use: Plan Explorer
Rdeči Noski – Charity

Rdeči noski

100% of donations made here go to charity, no deductions, no fees. For CLOWNDOCTORS - encouraging more joy and happiness to children staying in hospitals (http://www.rednoses.eu/red-noses-organisations/slovenia/)

€2.00

Top SQL Server Bloggers 2018
TomazTsql

Tomaz doing BI and DEV with SQL Server and R, Python, Power BI, Azure and beyond

Discover WordPress

A daily selection of the best content published on WordPress, collected for you by humans who love to read.

Revolutions

Tomaz doing BI and DEV with SQL Server and R, Python, Power BI, Azure and beyond

Reeves Smith's SQL & BI Blog

A blog about SQL Server and the Microsoft Business Intelligence stack with some random Non-Microsoft tools thrown in for good measure.

SQL Server

for Application Developers

Business Analytics 3.0

Data Driven Business Models

SQL Database Engine Blog

Tomaz doing BI and DEV with SQL Server and R, Python, Power BI, Azure and beyond

Search Msdn

Tomaz doing BI and DEV with SQL Server and R, Python, Power BI, Azure and beyond

R-bloggers

Tomaz doing BI and DEV with SQL Server and R, Python, Power BI, Azure and beyond

Data Until I Die!

Data for Life :)

Paul Turley's SQL Server BI Blog

sharing my experiences with the Microsoft data platform, SQL Server BI, Data Modeling, SSAS Design, Power Pivot, Power BI, SSRS Advanced Design, Power BI, Dashboards & Visualization since 2009

Grant Fritchey

Intimidating Databases and Code

Madhivanan's SQL blog

A modern business theme

Alessandro Alpi's Blog

DevOps could be the disease you die with, but don’t die of.

Paul te Braak

Business Intelligence Blog

Sql Insane Asylum (A Blog by Pat Wright)

Information about SQL (PostgreSQL & SQL Server) from the Asylum.

Gareth's Blog

A blog about Life, SQL & Everything ...

SQLPam's Blog

Life changes fast and this is where I occasionally take time to ponder what I have learned and experienced. A lot of focus will be on SQL and the SQL community – but life varies.

William Durkin

William Durkin a blog on SQL Server, Replication, Performance Tuning and whatever else.

$hell Your Experience !!!

As aventuras de um DBA usando o Poder do $hell

Design a site like this with WordPress.com
Get started