Monday, November 12, 2018

Azure Managed Instances Procuring & Connecting




Azure Managed Instances
Procuring & Connecting





Below steps help you creating a new Azure Managed Instance from Azure portal and shows how to connect to it.

  1. Create a new managed instance in Azure portal. Click on “Create a resource” and search for “Azure SQL Managed Instance”. In the result that appears. Click Create.





    2. Provide Instance Name, Login information, resource group, location and  Virtual Network to host managed instance. We are using below settings.

Resource Group - NaviDemoDBAInstance
Instance Name - navidemodbainstance
User Name - NaviSQLAdmin
Password - "Your Password"

Once all information is provided click create.

Create Managed Instance


           3. You will get a warning while creating a new VNet that First instance in the VNet could take upto 6 hours to complete.



       4.  Once the creation is in progress, you can click on the notification bell icon and choose to view the progress of the operation. Ours took 3 Hours and 37 Mins to complete.




               5. Create a new Virtual network for the VM you will connect your instance through. We are creating it in the same region “East US”.





               6. Create a new VM in the same resource group. Use the VNet “MyJumpVMVNet” for this Virtual machine. We opened the RDP ports to this machine.



Machine Name – MgdInstJumpVM
User Name – NaviSQLAdmin
Password - "Your password"

Below is the configurations of the VM created.



             7. Once done create a peering between the VM Vnet and Managed Instance VNet. Below are the 2 networks we will peer.


             8. Go to “Peerings” section of one of the network and click “Add”.


         9. On the blade that opens up, specify a name for peering and select the other Virtual network. In our case it is the Managed instance network selected.


               10. Once created you should have the peering visible on your VM Network


               11. Now go to the Managed instance Virtual network and create peering towards your VM Virtual network as we did before in other direction.




               12. Now Connect to your VM created earlier. You can download the RDP file from the portal for connection. Use the credentials provided while creation of VM.



          13. Once logged in Open Internet explorer and download the latest version of SQL Server Management Studio. We will use this for testing connectivity between VM and our Managed Instance.


                14. Once downloaded Start the setup and install it on your Azure VM


                15. Now go to you managed instance on azure portal and copy the complete Instance name. Instance name should be like “MyInstancename.3ed349523e65.database.windows.net”



                16. Go to your VM, Open SQL Server Management Studio and paste the server name and login information as below


                17. You should be able to connect to your instance now. By default the version you will receive would be SQL Server 2014 RTM (12.0.2000.8).


Hope you find the steps helpful and easy to follow.

Migrate On premise physical machines to Azure using Azure Site Recovery

Hello Everyone,

Below video shows the detailed step by step method to migrate an On-premise Physical server to Azure using Azure site recovery.

I have used 2 physical servers: 1 as Configuration server and other one as the Source server for migration. You will see detailed steps to configure everything from start till end. It also shows a test fail over to Azure and how to connect to the migrated server.

Due to some technical difficulties, the video doesn't has audio. But I hope you will find this useful as it is a complete step by step from start till end.



Wednesday, April 25, 2018

Reporting Service Key Backup Script

A lot of us have gone through the scenario where a Reporting Service account gets changed/deleted and then we don't have a way to get our reports working as all the encrypted content is lost.

Our organization needed an automated way to backup the Reporting Service key. Here is a simple script which will create a job on your SQL Instance. This job will run once a day taking RS Key backup with a random password. It will put the Key file and the Random password in the folder specified in the script and retain these for last 7 days. Go ahead and give it a try.

Please replace the value for variables $KeyPath(Location where key backup will be placed), $PwdFilePath(Location where password file will be placed) and $Daysback (Number of days to retain the key in the destination folder. Default is 7).


--******Start of Script*******
USE [msdb]
GO

/****** Object:  Job [Navi_SSRS_Key_Backup]    Script Date: 25/04/2018 08:23:09 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 25/04/2018 08:23:09 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'SSRS_Key_Backup', 
@enabled=1, 
@notify_level_eventlog=0, 
@notify_level_email=0, 
@notify_level_netsend=0, 
@notify_level_page=0, 
@delete_level=0, 
@description=N'No description available.', 
@category_name=N'[Uncategorized (Local)]', 
@owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [SSRS Key Backup]    Script Date: 25/04/2018 08:23:09 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'SSRS Key Backup', 
@step_id=1, 
@cmdexec_success_code=0, 
@on_success_action=1, 
@on_success_step_id=0, 
@on_fail_action=2, 
@on_fail_step_id=0, 
@retry_attempts=0, 
@retry_interval=0, 
@os_run_priority=0, @subsystem=N'PowerShell', 
@command=N'Function GET-Temppassword() {

Param(

[int]$length=10,

[string[]]$sourcedata

)



For ($loop=1; $loop –le $length; $loop++) {

            $TempPassword+=($sourcedata | GET-RANDOM)

            }

return $TempPassword

}

$ascii=$NULL
For ($a=33;$a –le 126;$a++) {$ascii+=,[char][byte]$a }
$password = GET-Temppassword –length 19 –sourcedata $ascii

$postfix = Get-Date -format "yyyyMMddhhmm"
$KeyPath = ''C:\MSSQL11.MSSQLSERVER\MSSQL\SSRSEncBackup\''
$PwdFilePath = ''C:\MSSQL11.MSSQLSERVER\MSSQL\SSRSEncBackup\KeyPwd''+$postfix+''.txt''
$KeyFileName = ''SSRSDBkey'' + $postfix + ''.snk''
$KeyFile = $KeyPath + $KeyFileName
echo y | rskeymgmt -e -f $KeyFile -p $password

$file = $PwdFilePath + $FileName

(get-date).ToString() + " | " + $password | Out-File -FilePath $PwdFilePath

$Daysback = “-7”
$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)
Get-ChildItem $KeyPath -Recurse | Where-Object { $_.LastWriteTime -lt $DatetoDelete } | Remove-Item', 
@database_name=N'master', 
@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'SSRSKeyBackup', 
@enabled=1, 
@freq_type=4, 
@freq_interval=1, 
@freq_subday_type=1, 
@freq_subday_interval=0, 
@freq_relative_interval=0, 
@freq_recurrence_factor=0, 
@active_start_date=20171118, 
@active_end_date=99991231, 
@active_start_time=233000, 
@active_end_time=235959, 
@schedule_uid=N'4fb8bbee-b128-4c0e-9005-2e966b872544'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

GO
--******End of Script*******

Hope it helps.

Saturday, April 8, 2017

SQLLocalDB - A temporary Instance available always

What is LocalDB:


A lot of times we find ourselves in a need to get a quick local instance to test some scenarios out. Installing a new instance might take a lot of time and we might not always have space for it.LocalDb is a cut down version of SQL Server that was specifically designed to be light-weight and easy to start and stop quickly. This means a compromise so there are some restrictions for it, but it really is a great choice for most developers because you can quickly create, use and destroy instances that are specific to one particular user. LocalDb has some additional benefits: The utility is shipped with the standard installation of SQL server. It shares the same binaries for each instance so you do not have to use up lots of disk space for each instance that you need. This means that it is really simple to start one up if you find that you need a new instance in the heat of a development session.

How to Create a LocalDB Instance:
Creating a new LocalDb is simple: You just type the following at the command shell:
sqllocaldb create “instance name”
This will create a new instance that you can use called “instance name”, on my machine it takes about 4 seconds to create a new instance and then about another 2 seconds to start the instance. Installing a new instance of any of the other types of SQL Server is measured in minutes to hours.
If you have multiple versions of LocalDb installed, you can create any of those versions really easily, just by executing this code in a command shell:

Sqllocaldb versions

You should get something like this depending on the versions of SQL servers installed.






Let’s say you need a SQL 2014 instance you can use a command like this –
sqllocaldb create “instance name” 12.0.

You would get a new SQL Server 2014 instance you could connect to.

Connecting to a LocalDB Instance:
Connecting to a LocalDB instance is a little bit different than the locally installed instance. If you are connecting to a local named instance you would use the machine name followed with the instance name separated with back slash. For a LocalDB Instance you will use (local)\InstanceName representation to get connected.














Checking the instances currently configured:

Currently configured (started or stopped) instances can be checked by using below command –

sqllocaldb info

You can extend this command to get details regarding a specific instance as below –

sqllocaldb info “instance name”

This command will give you the following details regarding the instance mentioned –
1.    Instance Name
2.    Version
3.    Instance Owner
4.    Instance state (Started/Stopped)
5.    The last start time







If it is started, it also gives the path of the named pipe it is running on. If you have a client that does not understand the (localdb)\instancename then perhaps you can connect over named pipes to the instance.
LocalDb is great for developing because it is so fast to create and start instances, if you often work on different projects you can stop and start instances and have lots of different instances available without the overhead of having to maintain them and store them on disk.


Benefits of LocalDb for development:

  • Fast development, it is simple to create new instances for development and testing.
  • Shares binaries between all instances of the same version so you do not take up lots of disk space or have to maintain many different versions
Cosiderations of LocalDb for development:
  • Does not include some fundamental features such as SQL Agent
  • Does not support FILESTREAM
  • Cannot be a merge replication subscriber,
  • Only allows local queues for Service Broker.
  • Always runs under the users security context

Friday, August 29, 2014

Generating a Backup Report

Did you ever had to generate a report for all the servers in your organization where you had to present the details of how the backups are happening on the server.

Today, let's create a simple job which will send out the details of the backups taken on the servers and alert you which databases stand in a vulnerable position in a well formatted HTML report. 

This job will let you specify, till how many days the backups fails before it alerts you, so that you can specify the threshold. I have only created this to filter out on Full database backups (because that's what I had to implement in my organization ;) and I am too lazy to generalize it for everything). Please go ahead and play around with the script to suit your needs.

So without further discussion, let's jump to the scripts. This job will have a couple of steps to generate header and footer for our HTML document. One step each for all the servers we want to monitor and last step to send the html file over email. Simple enough ...

So the structure of the job would look something like this

Step 1: Create Header
Step 2: MyServer1
Step 3: MyServer2
.
.
.
.
Step n-1: Create Footer
Step n: Send Mail

Each of these job steps except for the last one has a setting to push the output to a HTML file, which will be sent in the last step.


Step 1: 

This step is a sqlcmd job step, which will run against the server where we are creating the Backup Report job. It does nothing interesting except pushing our text string to a file. Replace JobServer with the server name where job will be created

sqlcmd -S "JobServer" -Q "Declare @TableHead varchar(max);Set NoCount On;Set @TableHead = '<html><head><style>td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;}</style></head><body><table cellpadding=0 cellspacing=0 border=0><tr bgcolor=#FFEFD8><td align=center><b>Server Name</b></td><td align=center><b>Database Name</b></td><td align=center><b>Backup Type</b></td><td align=center><b>Days Since Last Backup</b></td><td align=center><b>Last Backup Date</b></td></tr>';PRINT @TableHead"

And I know there are easier ways to do this. Please, no discussion on that. :)

Step 2:

This step will be created for each server whose details needs to be included in our Backup report.

The first part is the query which runs and extract the data joining  sys.sysdatabases and msdb.dbo.backupset tables. This pushes the data into a temporary table #BACKUPDATA. This data is then converted to XML by WITH XML tag in the next select statement.
All the magic happens here. Instead of converting this data to XML, we have specified the tags in such a way that we get formatted HTML from our FOR XML clause.
For each of the server, when you create a new step, replace Server1 with your server name
In the last section of this query, we have used a Replace function. This is just to ensure that the characters returned from FOR XML clause are properly displayed in our HTML report.
TempDB and model are excluded from the list of database using a NOT IN clause. You can add or remove databases as per your requirements.

sqlcmd -E -S Server1 -Q "Declare @Body varchar(max);Set NoCount On;CREATE TABLE #BACKUPDATA (ServerName nvarchar(40), DBName nvarchar(100), BackupType nvarchar(15), [DaysSinceLastBackup] nvarchar(10), [LastBackupDate] nvarchar(10));INSERT INTO #BACKUPDATA SELECT 'Server1' AS [ServerName], B.name as [DBName], case A.type when 'D' THEN 'Full Backup' when 'L' THEN 'Differential' end  AS [Type], ISNULL(STR(ABS(DATEDIFF(day, GetDate(),MAX(Backup_finish_date)))), 'NEVER') as [DaysSinceLastBackup] /*DaysSinceLastBackup*/, ISNULL(Convert(char(10), MAX(backup_finish_date), 101), 'NEVER') as [LastBackupDate] /*LastBackupDate*/ FROM master.dbo.sysdatabases B LEFT OUTER JOIN msdb.dbo.backupset A ON A.database_name = B.name AND A.type = 'D' where Database_Name not in ('tempdb', 'model') GROUP BY B.Name , A.type; 
SELECT @Body = (SELECT [ServerName] AS [TD], [DBName] AS [TD], BackupType AS [TD], [DaysSinceLastBackup] AS [TD], [LastBackupDate] AS [TD] FROM #BACKUPDATA WHERE [DaysSinceLastBackup]>3 ORDER BY [DBName] FOR XML RAW('TR'), ELEMENTS);Set @Body = Replace(@Body, '_x0020_', space(1));Set @Body = Replace(@Body, '_x003D_', '=');Set @Body = Replace(@Body, ' 1', ' ');Set @Body = Replace(@Body, '0', '');PRINT @Body;DROP TABLE #BACKUPDATA;"

This step will also require the similar setting as before, only difference is that the Append check box is checked on these steps.






Step 3: 

This step is so simple to understand, that it would be an insult to you if I even try to explain. Just replace JobServer with the name of the server where you are creating the job.

sqlcmd -S "JobServer" -Q "PRINT '
'"

Step 4:

The last step is to Bulk insert our HTML file to a variable and send this variable in an email to the designated people.
declare @data as nvarchar(max)

Select @data = Bulkcolumn FROm OPENROWSET
(BULK'J:\Microsoft SQL Server\backup.html', SINGLE_BLOB)X

exec msdb.dbo.sp_send_dbmail @profile_name= 'AuditAlert', 
@body = @data,
@body_Format = 'HTML',
@recipients = 'mygroupid@mycompany.com; myid@mycompany.com',
@subject = 'Production Server Backup Report'


Do make sure that you change the location of the HTML file throught the script and in the Job Step properties window, as per the disk location of your Job Server.

You can further enhance this script by not using one job step each for all your servers (as it might not be possible in a bigger environment), but having only one step, which picks up the server names from a table and loops through it. At every loop step, it can push the data into our HTML file. But we might do this on another day.

Till then.... implement this one. More to come soon.

Thursday, November 17, 2011

Microsoft SQL Server 2012 RC0 Released

Hi Guys, So finally after a long wait, while you patiently used SQL Server Code Name "Denali", Microsoft has finally released the Release Candidate for SQL Server 2012. Its officially available to be downloaded from Microsoft Website at

http://www.microsoft.com/download/en/details.aspx?id=28145

Take a sneak peak and start playing around with all the new features of it. 

Wednesday, June 29, 2011

How to get a SSRS report exported in multiple excel sheets

Hi,

In this post, we will address an issue relating to exporting a SSRS report.

One of my client had a report which showed data from 2 different Datasets in one Report. Everything looked fine to him, by the time he didn't exported it, since the data from 2 different datasets was imported in the same excel sheet.

To resolve the issue, all we really need to do is set a simple setting. You must be using 2 Tablix controls in your report to show the data. Just go to the properties of the first Tablix and set the value of Page Break -> Break Location to End. The default value should be null.



Figure 1 - Default Setting                                    Figure 2 - Changed Setting


Now when you will export the Report data. It will be exported to 2 different sheets in the Workbook. You can do the same for multiple Tablix in the same reports :-). Cool Huh...