Wednesday, February 8, 2017

Fixing Hot-Key issue in SSMS in five steps.

A lot of people in the Internet complain about their version of SSMS "forgot" some hot-key combinations. The oldest complain I remember was about the most useful combination "Ctrl-R".

The reason why SSMS "forgets" is within code sharing and reusability with other Microsoft development products.
If you have that problem, most probably I have (or had in the past) installed something else from Microsoft, such as Development Studio, Data Tools etc.

Won't concentrate on that, just provide the solution:

At first, got to the "Options":
- Menu -> Tools -> Options

- Or just simply press Alt+T -> O

Then Open "Environment" -> "Keyboard" -> "Keyboard".

Click to the text box on lower right called: "Press shortcut keys" and press "Ctrl+R"

In the correct environment you should see something like this:
In the drop down box "Shortcut currently used by:" you should see an option "Windows.ShowResultsPane (Ctrl + R (SQL Query Editor))"

If you do not have it - that is your problem.

For the sake of a Demo, I'll remove it in my SSMS and will fix it step-by-step.

Here is the Fix:

Step 1.

Go to Menu -> Tools -> Options -> Environment -> Keyboard -> Keyboard

Step 2.

In the Left-Middle ListBox search for a value "Windows.ShowResultsPane" and select it.
You should get something like this:

Step 3.

In drop down box "Use new shortcut in:" select "SQL Query Editor" and in "Press shortcut keys" text box press "Ctrl+R" to get something like this:

Step 4.

Press "Assign" button.
By doing this you assign key combination "Ctrl+R" to "Windows.ShowResultsPane" event within "SQL Query Editor" environment.
As the result, you have to get a new line in "Shortcuts for selected Command:" drop down box: "Ctrl+R (SQL Query Editor)".

Step 5.

Press OK and test how "Ctrl+R" works.


It looks easy, isn't it? The complication is only in the fact that Configuration options in SQL Server Management Studio show and allow to change shortcut keys not only for SSMS, but for other applications too.

If you have a problem with other unassigned hot keys the biggest problem is to identify "command" to assign for the key you need.

Here is a small list of commands for the most useful keys:
Shortcut KeyCommand
Ctrl + TQuery.ResultstoText
Ctrl + DQuery.ResultstoGrid
Ctrl + Shift + FQuery.ResultstoFile
Ctrl + NFile.NewQuery
Ctrl + SFile.SaveSelectedItems
Ctrl + OFile.OpenFile
Ctrl + FEdit.Find
Ctrl + HEdit.Replace
Ctrl + ZEdit.Undo
Ctrl + YEdit.Redo
Ctrl + AEdit.SelectAll
Ctrl + CEdit.Copy
Ctrl + VEdit.Paste
Ctrl + XEdit.Cut
Ctrl + Shift + UEdit.MakeUppercase
Ctrl + Shift + LEdit.MakeLowercase
Ctrl + K, Ctrl + CEdit.CommentSelection
Ctrl + K, Ctrl + UEdit.UncommentSelection
Ctrl + LQuery.DisplayEstimatedExecutionPlan
Ctrl + MQuery.IncludeActualExecutionPlan
Ctrl + JEdit.ListMembers

Tuesday, January 31, 2017

Troubleshooting connectivity to SQL Server on Linux

In general, the connectivity to SQL Server on Linux is similar to connectivity to SQL Server on Windows, but because I do not have blog about Windows I'll do it for Linux.

Prerequisites:

  • Virtual Machine or bare metal server with installed Linux;
  • Successfully installed SQL Server on Linux;
  • Successfully installed SQL Server Tools on Linux (optional);

Step 1: Verification that SQL Server up and running:

Very simple code to run in Linux:
#> systemctl status mssql-server

As a result you have to get something like this:

If you did not get that output there might be three most probable problems:
I) Your SQL Server is not installed on that machine. Just try to install it again.

II) SQL Server is not configured. To configure run following command:
#> sudo /opt/mssql/bin/sqlservr-setup

III) Your SQL Server is not started. To fix that just start it:
#> sudo systemctl start mssql-server

Step 2: Check that SQL Server is responding.

After you verified SQL Server is up and running, you configured it and set SA password you can test SQL Server Tools connectivity:
#> sqlcmd -S localhost -U SA -Q "SELECT @@VERSION;"

After you enter SA password you have to get "vNext" version of your SQL Server.
If you did not get the correct response you might have following problems:
I)   Wrong SA password. To fix it, just re-configure SQL Server.
II)  SQL Server Tools are not installed.
III) Typo. Check your syntax.

Step 3: Check network connection to Linux machine.

At first, verify IP addresses of all network cards of your Linux machine:
#> ifconfig | grep 'inet addr:'

From the machine, you want to establish connection to the SQL Server on Linux, ping Linux machine by an IP address you've got by the previous command:
> ping 192.168.58.11

If you can't get a response from pinging Linux machine that tells about network connectivity issues.
You have to use your networking skills to troubleshoot that problem.

Step 4: Check port on the Linux machine.

At first, make sure which port is used by your SQL Server on Linux. By default it is 1433, but to verify it you can run following command:
#> cat /etc/services | grep 'Microsof SQL Server'

As the result you will see the real port SQL Server is assigned too.

Next, you can check if SQL Server port is accessible from windows machine using "PortQry" Command (you can download the executable from Microsoft site), IP address of your Linux machine and assigned SQL Server port :
> PortQry.exe -n 192.168.1.10 -e 1433

That command will determine if port 1433 is accessible on that machine and that SQL Server is listening to it.

If the port marked as "FILTERED" that means Linux firewall is blocking any incoming calls to that port.

In order to fix that you have to open SQL Server port on Linux machine and restart firewall using following two commands:
#> sudo firewall-cmd --zone=public --add-port=1433/tcp --permanent
#> sudo firewall-cmd --reload

Step 5: Connect to SQL Server on Linux.

If all previous steps were successfully accomplished, you have to be able to connect to SQL Server on Linux machine using following command from Windows or another Linux machine:
> sqlcmd -S "192.168.1.10,1433" -U SA -Q "SELECT @@VERSION;"

Hopefully, I've covered the most often problems of connectivity to SQL Server with specifics of Linux.
If you have any questions or still have troubles please ask me in comments.

Tuesday, December 20, 2016

Four newest T-SQL features.


In the very beginning I want to warn you:
These new language features are not available in the SQL Server product yet. Only in Community Technical Preview. Moreover, the Community Technical Preview (CTP 1.1) is available for Linux Edition of SQL Server.

Official notes on the product: https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-whats-new

So, here they are:

Four newest T-SQL features:

#1. Trimming.

Count, how many times in your SQL programming life you've used the construction "RTRIM(LTRIM(...))" to get rid of empty spaces at the beginning and at the end of a string.
How many times you have wished to have a simple function "TRIM" to do the job?
And here it is:

DECLARE @C CHAR(10) = '   ABC    ';
PRINT 'My new nice Trimming: "' + TRIM(@C) + '"';
GO

#2. String Concatenation.

How do you usually do string concatenation in T-SQL?
Probably something like this:
DECLARE@A VARCHAR(10) = 'ABC';
DECLARE @B VARCHAR(10) = 'DEF';
DECLARE@C VARCHAR(10) = 'GHJ';
PRINT @A + ';' + @B + ';' + @C;
GO

Now you can do it another way, using function "CONCAT_WS":
DECLARE@A VARCHAR(10) = 'ABC';
DECLARE @B VARCHAR(10) = 'DEF';
DECLARE@C VARCHAR(10) = 'GHJ';
PRINT CONCAT_WS(';', @A, @B, @C);
GO

You might ask me "Why do we need this?". My guess would be "-To simplify the invasion."
In other words make a migration from MySQL to SQL Server less painful.

#3 String Aggregation.

That is the really good one.
Since Microsoft introduced XML support in SQL Server, the most common string concatenation technique was use of "XML PATH('')" like this:

SELECT SUBSTRING(
(SELECT ', ' + name FROM master.sys.tables
FOR XML PATH(''))
,3,8000);
GO

Now you can aggregate your strings by using function "STRING_AGG":
SELECT STRING_AGG(name, ', 'FROM master.sys.tables;

Edit: 2017-01-26
Now you can aggregate your strings by using function "STRING_AGG" with ordering by certain field:
SELECT STRING_AGG(name, ', ')  WITHIN GROUP ( ORDER BY object_id DESC)
FROM master.sys.tables;

#4 Translation.

Microsoft introduced new T-SQL function "TRANSLATE", which simply replaces characters within a string. For a string you want to do a replacement for you have to specify two series of characters: one is "originals" and second is "replacements". Both these series must have equal length.

PRINT TRANSLATE ( 'This is my unencrypted message',
'abcdefghijklmnopqrstuvwxyz',
'mnopqrstuvwxyzabcdefghijkl' );
GO

The result will be "ftue ue yk gzqzodkbfqp yqeemsq".
If we replace the original string by the result and switch second and third parameters we can get our original string as a result:

PRINT TRANSLATE 'ftue ue yk gzqzodkbfqp yqeemsq',
'mnopqrstuvwxyzabcdefghijkl',
'abcdefghijklmnopqrstuvwxyz' );
GO

Looks awesome, isn't it?
However, the restriction that second and third parameters are must be same size makes this function not usable for conversion of text for XML, where we have to replace special 5 XML characters: "&'<">".
Also, if we want to keep consistency of capitalization, our database must be in case sensitive collation.

Friday, December 16, 2016

SQL Server on Linux in 2016

This Blog post highlights only current state and future expectations of Microsoft's "SQL Server on Linux" project in EOY 2016.

Beginning

As you've already heard, Microsoft had made a daring move and decided to go to the "Enemy" territory with their flagship product SQL Server.
That is actually not the first attempt of Microsoft to go with Linux. The most known known first invasion was with Linux based Hadoop clusters in Microsoft Azure: https://docs.microsoft.com/en-us/azure/hdinsight/hdinsight-hadoop-linux-tutorial-get-started

So the current timeline for SQL On Linux looks like this:
- March, 2016 - first public announcement at a conference in NYC and starting it's private preview and testing;
- November, 2016 - After several monthly releases preview became public with CTP 1 (Community Technology Preview);
- Middle 2017 - Production market target for the product;

Why SQL Server on Linux? Our expectations.

At first will take a look at the pricing of one mid-size SQL Database server:
Windows 2016 Datacenter license cost (16 cores):           $6,155
SQL Server 2016 Enterprise license cost (16 cores):        $114,048
Total cost for 16 cores :                                                    ~$120K

I fill like it is pretty expensive. What do you think?

Alternatives

So, businesses currently have following "free"* alternatives based on Linux:
MySQL
PostgreSQL
MariaDB

* I put word "free" in quotes because it does not include all associated risks.

Main risks of "free" solutions:

1. Security.
2. Scalability.

If you are small company, which does not store any customers' data in a database you might be OK with security. However, if you expect your line of business to grow 10 times in the next 5 years?
Will current free Linux databases be sustainable enough to support your database then?

Think about all development effort you put in free database product and about an effort to migrate that database to enterprise level with Oracle or Microsoft.

So, the solution is simple: Go with SQL Server on Linux!

SQL Server on Linux provides all necessary security and it is scalable to the enterprise level without any extra-migration programming effort.

Expectations:

(Disclaimer: I'm not working for Microsoft and do not have a Crystal Ball. All my expectations are only MINE and can go as knowledgeable suggestions. You can disagree or agree and support me)

So, I'd expect Microsoft to provide free version of SQL Server on Linux (Express/Small Business) with following limitations:
  1. CPU - up to 4 cores;
  2. Memory - up to 16 Gb;
  3. DB Size - up to 100 Gb;

I know, adepts of Microsoft will say: "-We can't give such a wonderful product for free!".

For that I have a justification from Oracle:

In year of 2000, when Microsoft gave away free SQL Server Desktop edition called MSDE, the limit in database size was 2GB!
Look at the diagram and compare it with 2016 limit in 10 GB.
So, if we are targeting going into production in 2017 with most of customer project deployments started in 2018, current SQL Express limitations will be absolute No-No for any business case scenario.

That might be against Microsoft line of business to give away free business product, but that move would make SQL Server #1 database in the world. People would forget about any other free alternatives.

I think only one argument might stop Microsoft from following that scenario. As I mentioned earlier, domination of Microsoft in the Database segment of the world market would make it a monopoly with all following consequences. 

Currently Supported features:

Database engine:

  • In-Memory OLTP; 
  • Updatable Columnstore Indexes; 
  • JSON Support;
  • Query Store; 

High Availability:

  • Failover clustering;

Security:

  • Only SQL Server authentication is currently available; 
  • Row Level Security; 
  • Dynamic Data Masking;

Services:

  • SQL Server Service;

SQL Server on Linux Target Audience

If my expectations become true in the middle of 2017 than here is a small list of beneficiaries: 
  • Small businesses – Low cost;
  • New businesses – Low cost with big potential growth;
  • Enterprise businesses – Reduced cost on multiple servers;
  • SQL Server oriented teams;

In the nearest future I'll cover some technicals of SQL Server on Linux.
So, please follow my blog and expect more.

Tuesday, September 13, 2016

Configuring Windows Firewall for SQL Server using PowerShell

You can configure Windows Firewall using GUI or you can ask your sysadmin to do it, but what if you do not have Sysadmin or GUI?
Also, if you have to document your configuration, the PowerShell scripts that exactly what you need.
As it was said: "One line of PowerShell worth 15 GUI screen shoots".

The very first script I want to introduce is the collection of Firewall basic information.
That Script does not collect ALL information, only the most common for handling SQL Server requests.

Description: Returns list of firewall rules, which are protocol set as "TCP" or "UDP" or have set associated application.
That script has the purpose of identifying any relevant rule in the long list.
For instance you might already have a SQL Server related rule, but it is disabled or addresses wrong port or even blocking a port. And you definitely do not want to have collisions nor duplicates.

The Script has list of adjustable filters:
$Direction - Direction of firewall rule: Inbound or Outbound;
$Action - Action rule performs: Allow or Block;
$Enabled - Status of a rule: Enabled - True or False;
$RuleGroup - Group rule has been assigned. By default script uses "$Null" variable, which filters all rules without assigned group. However you can specify a group a name if necessary;
$DisplayName - Name of a rule. By default I use an expression "*SQL*" to search for rules which have word "SQL" in their name. To retrieve all rules us "*". To retrieve any particular rule use rule name.

cls
$Direction = "Inbound"  # Options: "Inbound"/"Outbound"
$Action = "Allow"       # Options: "Allow"/"Block"
$Enabled = "True"       # Options: "True"/"False"
$RuleGroup = $Null      # Options:  $Null / Gropup Name
$DisplayName = "*SQL*"  # Option:  "*SQL*" / "*" / Any regular expression

$Firewall = @()
$Rules = Get-NetFirewallRule |`
       where { $_.Direction -eq $Direction} |`
       where { $_.Action -eq $Action} |`
       where { $_.Enabled -eq $Enabled} |`
       where { $_.RuleGroup -eq $RuleGroup} |`
       where { $_.DisplayName -like $DisplayName} |`
       Select DisplayName, RuleGroup, InstanceID, Enabled, Direction, Action
foreach ($App in Get-NetFirewallApplicationFilter | Select Program, InstanceID)
{
       $InstanceID = ($App | Format-Table -Property InstanceID -HideTableHeaders | Out-String).Trim()
       $Rule = $Rules | Where { $_.InstanceID -eq $InstanceID}
       $DisplayName = ($Rule.DisplayName + "").Trim()
       If ($DisplayName -ne ""  -or $DisplayName -like "*SQL*" ) {
              $Program = ($App | Format-Table -Property Program -HideTableHeaders | Out-String).Trim()
              $Ports = Get-NetFirewallPortFilter | Where { $_.InstanceID -eq $InstanceID}

              If ($Ports.Protocol -eq "TCP" -or $Ports.Protocol -eq "UDP" -or $Program -ne "Any") {
                     $Firewall += New-Object -TypeName PSObject -Property @{
                           DisplayName = $DisplayName
                           RuleGroup = $Rule.RuleGroup
                           Direction = $Rule.Direction
                           Action = $Rule.Action
                           Enabled = $Rule.Enabled
                           Protocol = $Ports.Protocol
                           LocalPort = $Ports.LocalPort
                           RemotePort = $Ports.RemotePort
                           RemoteAddress = (Get-NetFirewallAddressFilter | where { $_.InstanceID -eq $InstanceID}).RemoteAddress
                           Program = $Program
                           InstanceID = $InstanceID
                     } 
              }
       }
}
$Firewall | Format-table -AutoSize -Property DisplayName, RuleGroup, Direction, Action, Enabled, Protocol, LocalPort, RemotePort, RemoteAddress, Program

You just have to copy paste that script, maybe do little filter adjustments and paste it into PowerShell window, which is supposed to run under Administrator's privileges.

Here is what you should expect:

If you want to research one of the returned rules alone you can run following script right after by just specifying rule's DisplayName like this:


$DisplayName = "SQ Test 1"
$Firewall | Where { $_.DisplayName -eq $DisplayName } |`
Format-List -Property DisplayName, RuleGroup, Direction, Action, Enabled, Protocol, LocalPort, RemotePort, RemoteAddress, Program, InstanceID



Result of that query returns very important "InstanceID", which you potentially can use to address some informational pieces of the Firewall Rule.

Now, when we identified existing rules or did not find appropriate one we can start doing changes:

Create a new rule



New-NetFirewallRule -DisplayName "SQL Server Access via Port 1433" -Direction Inbound -Action Allow -Protocol TCP –LocalPort 1433 -Description "SQL Server Port access Rule"

That script creates a new rule, which allows inbound connections via default SQL Server port 1433.

Enable/Disable rule


There are 2 methods to Enable/Disable rules: Using "Enable-NetFirewallRule" and "Disable-NetFirewallRule" or just by universal "Set-NetFirewallRule":


Enable-NetFirewallRule -DisplayName "SQL Server Access via Port 1433"
Disable-NetFirewallRule -DisplayName "SQL Server Access via Port 1433"

Set-NetFirewallRule -DisplayName "SQL Server Access via Port 1433" -Enabled True
Set-NetFirewallRule -DisplayName "SQL Server Access via Port 1433" -Enabled False

Edit Rule


The most common changes to a rule can be changing a Protocol, Port Number or list/range of remote computers, which can go through that rule:


Set-NetFirewallRule -DisplayName "SQL Server Access via Port 1433" -Protocol "UDP" -LocalPort 1434
Set-NetFirewallRule -DisplayName "SQL Server Access via Port 1433" -RemoteAddress "192.168.58.1-192.168.58.11","192.168.58.102"

You also can change "Profile" with values: Any, Domain, Private, Public, or NotApplicable;
If you are really want to secure your server you can dig into settings of "Authentication", "RemoteUser", "RemoteMachine", but to do so you'd need more advanced technics to access Active Directory and that might be area you do not want to go.

Delete rule


Obviously, if you created rule by mistake, or have a rule, which should not exist you can delete it by following:


Remove-NetFirewallRule -DisplayName "SQL Server Access via Port 1433"


After each command you can re-run the very first reporting script to make sure the changes you've made are correct.
Be aware that all changes will take immediate effect and you do not need to restart the server or even a service.


And that is it. Not a lot and pretty simple. Much easier for understanding and making any corrections than using GUI with all extra and often unnecessary features.