Advertisements

Archive

Posts Tagged ‘Row Level Security’

Implementing “Row Level Security” (RLS) with “Block Predicates” in SQL Server 2016 – Part 2

January 9, 2016 3 comments

In my [previous post] I discussed about Row Level Security, its introduction, and a detailed demo on how to implement it.

There I discussed about the Filter Predicate option available in the CTP 2.x release. With this option we can restrict read access for a user to avoid unauthorized access of rows.

Filter Predicates filters the read operations like SELECT, UPDATE and DELETE, but do not filter INSERT operations, and thus a user can INSERT any row (associate to another user also).
 

Here in this post I will talk about the new Block Predicate option available in the CTP 3.0 release. With this option we can restrict write access for specific users.

Block Predicates block all write operations like:

– AFTER INSERT and AFTER UPDATE

– BEFORE UPDATE

– and BEFORE DELETE

To know more about these write operations check MS BoL here.
 

I’m using the same script I used in my [previous post] about RLS with Filter Predicates.

–> Step #1. Create some test accounts and test data:

-- Let's create some test accounts:

-- Three users for The CEO, HR & Finance department admin users.
CREATE USER userCEO WITHOUT LOGIN;
GO
CREATE USER userHR WITHOUT LOGIN;
GO
CREATE USER userFin WITHOUT LOGIN;
GO
CREATE USER userAdmin WITHOUT LOGIN;
GO

-- Create a sample table [dbo].[Employee]: with a self-referencing Manager ID column.
CREATE TABLE dbo.Employee (
	[EmpCode] NVARCHAR(50),  -- Employee ID
	[EmpName] NVARCHAR(250), -- Employee/Manager Full Name
	[Salary]  MONEY,		 -- Fictious Salary
	[MgrCode] NVARCHAR(50)   -- Manager ID
);
GO

-- Now insert some test records:

-- Top Boss CEO
INSERT INTO dbo.Employee VALUES ('userCEO' , 'CEO Top Boss'  , 800, NULL)

-- Next 2 levels under CEO
INSERT INTO dbo.Employee VALUES ('userHR'  , 'HR User'		 , 700, 'userCEO');
INSERT INTO dbo.Employee VALUES ('userFin' , 'Finance User'  , 600, 'userCEO');

-- Employees under Kevin
INSERT INTO dbo.Employee VALUES ('manojp'  , 'Manoj Pandey'  , 100, 'userHR');
INSERT INTO dbo.Employee VALUES ('saurabhs', 'Saurabh Sharma', 400, 'userHR');
INSERT INTO dbo.Employee VALUES ('deepakb' , 'Deepak Biswal' , 500, 'userHR');

-- Employees under Amy
INSERT INTO dbo.Employee VALUES ('keshavk' , 'Keshav K'		 , 200, 'userFin');
INSERT INTO dbo.Employee VALUES ('viveks'  , 'Vivek S'		 , 300, 'userFin');
GO

-- Let's check the records before applying "Row Level Security":
SELECT * FROM dbo.Employee; -- 8 rows
GO

Output: As a normal SEELCT and without RLS, it just ignores my Execution Context and execute the Query and return all the 8 rows.
 

–> Step #2. Grant only SELECT to the CEO-User, and Grant SELECT, INSERT,UPDATE, DELETE access on the dbo.Employee table to all 3 users:

GRANT SELECT ON dbo.Employee TO userCEO;
GO
GRANT SELECT, INSERT, UPDATE, DELETE ON dbo.Employee TO userHR;
GO
GRANT SELECT, INSERT, UPDATE, DELETE ON dbo.Employee TO userFin;
GO
GRANT SELECT, INSERT, UPDATE, DELETE ON dbo.Employee TO userAdmin;
GO

 

The new “Row Level Security” feature lets you:

– apply this security at the database level

– create two predicate functions, Filter & Block Predicates.

– and there is no need to apply the WHERE clause to filter out unauthorized users.
 

–> Step #3a. Create an Inline Table-Valued Function to create a Filter Predicate function:

CREATE FUNCTION dbo.fn_SecurityFilterPredicateEmployee (@mgrCode AS sysname)
    RETURNS TABLE
WITH SCHEMABINDING
AS
    RETURN SELECT 1 AS fn_SecurityPredicateEmployee_result 
	-- Predicate logic
	WHERE @mgrCode = USER_NAME() 
	OR USER_NAME() IN ('userCEO', 'userAdmin'); -- the CEO and Admin should see all rows
GO

–> Step #3b. Create an Inline Table-Valued Function to create a Block Predicate function:

CREATE FUNCTION dbo.fn_SecurityBlockPredicateEmployee (@mgrCode AS sysname)
    RETURNS TABLE
WITH SCHEMABINDING
AS
    RETURN SELECT 1 AS fn_SecurityPredicateEmployee_result 
	-- Predicate logic
	WHERE @mgrCode = USER_NAME() 
	OR USER_NAME() = 'userAdmin'; -- the Admin should have SELECT, INSERT, UPDATE, DELETE access to all rows
GO

Both the functions returns value 1 when a row in the MgrCode (Manager ID) column is the same as the user executing the query (@@mgrCode = USER_NAME()) or if the user executing the query is the Top Boss user USER_NAME() IN (‘userCEO’, ‘userAdmin’) and (USER_NAME() = ‘userCEO’) respectively.
 

–> Step #4. Create a security policy adding both the functions for Filter & Block predicates:

CREATE SECURITY POLICY ManagerFilter
ADD FILTER PREDICATE 
	dbo.fn_SecurityFilterPredicateEmployee(MgrCode) ON dbo.Employee, 
ADD BLOCK PREDICATE 
	dbo.fn_SecurityBlockPredicateEmployee(MgrCode) ON dbo.Employee 
WITH (STATE = ON); -- The state must be set to ON to enable the policy.
GO

-- Now let's again check the records after applying "Row Level Security":
SELECT * FROM dbo.Employee; -- 0 rows, because my used does not have any access.
GO

Finally with the above 4 steps we’ve configured RLS with both Filter & Block predicates, to restrict unauthorized access and modification of data.
 


 

Note: to check and validate RLS with Filter Predicate while retrieving data (or SELECT) please refer my [previous post].
 

–> Now, let’s check and validate RLS with Block Predicate while Updating data (INSERT, UPDATE, DELETE):

Usage #1. First we will check our top boss ‘userCEO’ account which has just read/SELECT access:

EXECUTE AS USER = 'userCEO';
	SELECT * FROM dbo.Employee; -- 8 rows

-- 1. Insert:
	INSERT INTO dbo.Employee (EmpCode, EmpName, Salary, MgrCode) 
	VALUES ('akashm' , 'Akash M'  , 550, 'userCEO') -- error
/*
Msg 229, Level 14, State 5, Line 106
The INSERT permission was denied on the object 'Employee', database 'TestManDB', schema 'dbo'.
*/

-- 2. Update:
	UPDATE [dbo].[Employee] SET Salary = 900 WHERE EmpCode = 'akashm' -- error
/*
Msg 229, Level 14, State 5, Line 111
The UPDATE permission was denied on the object 'Employee', database 'TestManDB', schema 'dbo'.
*/

-- 3. Delete:
	DELETE FROM [dbo].[Employee] WHERE EmpCode = 'akashm' -- error
/*
Msg 229, Level 14, State 5, Line 118
The DELETE permission was denied on the object 'Employee', database 'TestManDB', schema 'dbo'.
*/
REVERT;
GO

As you can see above for ‘userCEO’ account all INSERT/UPDATE/DELETE operations failed on the Employee table, as it only has read/SELECT access.
nbsp;

Usage #2. Now let’s check the ‘userHR’ account which as all permissions on his data:

EXECUTE AS USER = 'userHR';
	SELECT * FROM dbo.Employee; -- 3 rows

-- 1. Insert:
	INSERT INTO dbo.Employee (EmpCode, EmpName, Salary, MgrCode) 
	VALUES ('akashm' , 'Akash M'  , 550, 'userHR')
	SELECT * FROM dbo.Employee; -- 4 rows

-- 2: Update:
	UPDATE [dbo].[Employee] SET Salary = 900 WHERE EmpCode = 'akashm'
	SELECT * FROM dbo.Employee; -- 4 rows, with Salary = 900

-- 3: Delete:	
	DELETE FROM [dbo].[Employee] WHERE EmpCode = 'akashm'
	SELECT * FROM dbo.Employee; -- 3 rows

-- 4. Update another user's row:
	UPDATE [dbo].[Employee] SET Salary = 1000 WHERE EmpCode = 'viveks'
	-- (0 row(s) affected)
REVERT;
GO

So, the ‘userHR’ account can modify his records in all 3 INSERT/UPDATE/DELETE operations. But the 4th UPDATE operation fails where he tries to update another user (‘userFin’) record. However this does not displays any error message, but the query output message clearly shows no records were updated.
 

Usage #3. Execute as our Admin who can insert record for any User:

EXECUTE AS USER = 'userAdmin';
	SELECT * FROM dbo.Employee; -- 8 rows

-- 1. Insert row for another user HR:
	INSERT INTO dbo.Employee (EmpCode, EmpName, Salary, MgrCode) 
	VALUES ('akashm' , 'Akash M'  , 550, 'userHR')
	SELECT * FROM dbo.Employee; -- 9 rows

-- 2. Insert row for another user Fin:
	INSERT INTO dbo.Employee (EmpCode, EmpName, Salary, MgrCode) 
	VALUES ('shantis' , 'Shanti S'  , 200, 'userFin')
	SELECT * FROM dbo.Employee; -- 10 rows

-- 3. Update other user's rows (HR & Fin):
	UPDATE [dbo].[Employee] SET Salary = 900 WHERE EmpCode IN ('akashm', 'shantis')
	SELECT * FROM dbo.Employee; -- 10 rows total, last 2 rows with Salary = 900

-- 4. Delete other user's rows (HR & Fin)::
	DELETE FROM [dbo].[Employee] WHERE EmpCode IN ('akashm', 'shantis')
	SELECT * FROM dbo.Employee; -- 8 rows
REVERT;
GO

And here you can see the ‘userAdmin’ account is able to update all rows belonging to other users as well, as it is configured to behave like that, and this logic is built into the Security function that we build above in Step 3.b, where the Predicate logic looks like this:

    -- Predicate logic
    WHERE @mgrCode = USER_NAME() 
    OR USER_NAME() = 'userAdmin';

 

–> Thus, by using Row Level Security feature in SQL Server 2016 you can build your own customized Security feature for Read & Write operations for Tables by creating Inline Table-Valued Functions with Filter & Block predicates which are linked to the Security Policy for respective tables.
 

–> Final Cleanup

USE [TestManDB]
GO
DROP SECURITY POLICY [dbo].[ManagerFilter]
GO
DROP FUNCTION [dbo].[fn_SecurityFilterPredicateEmployee]
GO
DROP FUNCTION [dbo].[fn_SecurityBlockPredicateEmployee]
GO
DROP TABLE [dbo].[Employee]
GO

 

Check the same demo on YouTube:

Check & Like my FB Page


Advertisements

Implementing “Row Level Security” (RLS) with “Filter Predicate” in SQL Server 2016 – Part 1

July 13, 2015 11 comments

For an Organization its Data is the most important thing, and the Org’s IT department takes lot of measures to make sure data does not fall in wrong hands. The DBA’s and Application programmers setup different layers of security on top of data so that the user is only able to see the Filtered data/rows from a table that he has access to. DB programmers normally create abstracted Views or Stored Procedures with complex logic on top of the Tables by using other master-mapping tables that contains the user-data access key. Sometimes these security logics are not upto the standards, and may have various versions on a database and thus it becomes difficult to track, update and make them fail-proof. So, with SQL Server 2016 the new Row Level Security feature is going to handle this Out of the Box and as a Standard.

RLS or Row Level Security is a feature that enables fine grained control over access to rows in a table, allowing you to easily control which users can access which data with complete transparency to the application.

With this feature rows are filtered based on the Execution Context of the Query, rather than the current user access rights. A secure logic can be created to determine which user can see which rows and restrict any kind of data (rows) by designing a flexible and robust Security policy for a table.

SQL Server 2016 - Row Level Security 04
 

–> To setup Row Level Security (RLS) on a particular table it needs only these simple steps:

1. Create Users and Grant Read/SELECT access for a Particular table.

2. Create a new Inline Table-Valued Function that will contain the Filter Predicate for that table. This Function Predicate can be a sophisticated business logic with multiple JOINs or a simple WHERE ManagerCode = ‘userHR’.

3. Create a new Security Policy for this table and add the above Function (Filter) Predicate to it.

Please note: that these Functions & Security Policies should be unique for a table. So to create RLS for an another table, you will need to create separate Function & Security Policy.
 

–> Step 1.a. Let’s create some test accounts: I will create three users for:

1. The CEO, over-all admin of the company data.

2. HR department head

3. Finance department head

CREATE USER userCEO WITHOUT LOGIN;
GO
CREATE USER userHR WITHOUT LOGIN;
GO
CREATE USER userFin WITHOUT LOGIN;
GO

 

–> Create a sample table [dbo].[Employee]: with a self-referencing Manager ID column.

CREATE TABLE dbo.Employees (
	[EmpCode] NVARCHAR(50),  -- Employee ID
	[EmpName] NVARCHAR(250), -- Employee/Manager Full Name
	[Salary]  MONEY,		 -- Fictious Salary
	[MgrCode] NVARCHAR(50)   -- Manager ID
);
GO

-> Now insert some test records:

-- Top Boss CEO
INSERT INTO dbo.Employees VALUES ('userCEO'	, 'CEO Top Boss'  , 800, NULL)

-- Next 2 levels under CEO
INSERT INTO dbo.Employees VALUES ('userHR'	, 'HR User'		  , 700, 'userCEO');
INSERT INTO dbo.Employees VALUES ('userFin'	, 'Finance User'  , 600, 'userCEO');

-- Employees under Kevin
INSERT INTO dbo.Employees VALUES ('manojp'	, 'Manoj Pandey'  , 100, 'userHR');
INSERT INTO dbo.Employees VALUES ('saurabhs', 'Saurabh Sharma', 400, 'userHR');
INSERT INTO dbo.Employees VALUES ('deepakb' , 'Deepak Biswal' , 500, 'userHR');

-- Employees under Amy
INSERT INTO dbo.Employees VALUES ('keshavk'	, 'Keshav K'	  , 200, 'userFin');
INSERT INTO dbo.Employees VALUES ('viveks'	, 'Vivek S'		  , 300, 'userFin');
GO

–> Let’s check the records before applying “Row Level Security”:

SELECT * FROM dbo.Employees; -- 8 rows
GO

As a normal SEELCT and without RLS, it just ignores my Execution Context and execute the Query and return all the 8 rows.

–> The Traditional way to setup the Row Level Security till now was as follows (a simple example):

-- Stored Procedure with User-Name passed as parameter:
CREATE PROCEDURE dbo.uspGetEmployeeDetails (@userAccess NVARCHAR(50))
AS
BEGIN
	SELECT * 
	FROM dbo.Employees
	WHERE [MgrCode] = @userAccess
	OR @userAccess = 'userCEO'; -- CEO, the admin should see all rows
END
GO

-- Execute the SP with different parameter values:
EXEC dbo.uspGetEmployeeDetails @userAccess = 'userHR'  -- only 3 rows
GO
EXEC dbo.uspGetEmployeeDetails @userAccess = 'userFin' -- only 2 rows
GO
EXEC dbo.uspGetEmployeeDetails @userAccess = 'userCEO' -- all 8 rows
GO

The above method is prone to issues, like SQL Injection and any other user can apply other user’s User-Name and get the information that he is not allowed to see. With this type of method you have to apply another security layer at the application level so whenever a user executes the SP it gets executed with the same user’s User-Name.
 

–> The new Row Level Security feature let you:
– apply this security at the database level
– and there is no need to apply the WHERE clause filter for the User-Name.

This makes the security system more reliable and robust by reducing the surface area of your security system.

–> Step 1.b. Grant Read/SELECT access on the dbo.Employee table to all 3 users:

GRANT SELECT ON dbo.Employees TO userCEO;
GO
GRANT SELECT ON dbo.Employees TO userHR;
GO
GRANT SELECT ON dbo.Employees TO userFin;
GO

 

–> Step 2. Let’s create an Inline Table-Valued Function to write our Filter logic:

CREATE FUNCTION dbo.fn_SecurityPredicateEmployee(@mgrCode AS sysname)
    RETURNS TABLE
WITH SCHEMABINDING
AS
    RETURN SELECT 1 AS fn_SecurityPredicateEmployee_result
	-- Predicate logic
	WHERE @mgrCode = USER_NAME() 
	OR USER_NAME() = 'userCEO'; -- CEO, the admin should see all rows
GO

This function returns value 1 when:

– a row in the MgrCode (i.e. the Manager Code) column is the same as the user executing the query (@@mgrCode = USER_NAME())

– or if the user executing the query is the Top Boss user (USER_NAME() = ‘userCEO’)
 

–> Step 3. Create a security policy adding the function as a filter predicate:

CREATE SECURITY POLICY ManagerFilter
ADD FILTER PREDICATE dbo.fn_SecurityPredicateEmployee(MgrCode)  -- Filter Column from dbo.Employee table
ON dbo.Employees
WITH (STATE = ON); -- The state must be set to ON to enable the policy.
GO

The above Security Policy takes the Filter Predicate Logic from the associated Function and applies it to the Query as a WHERE clause.
 

–> Now let’s again check the records after applying “Row Level Security”:

SELECT * FROM dbo.Employees; -- 0 rows, 
GO

The simple “SELECT *” statement will fetch me zero rows after applying RLS, as my user ID is not configured to have access to any of those rows & Table.

–> And if you check in the Execution Plan of above SELECT statement without WHERE clause, it will show you the Filter Predicate that is added by the Security Policy defined in Step #3 for applying RLS on this table, which looks like this:

[TestManDB].[dbo].[Employee].[MgrCode]=user_name()
OR user_name()=N’userCEO’

SQL Server 2016 - Row Level Security 10
 

–> Let’s check the 3 users we created and provided them customized access to the dbo.Employee table and rows in it:

-- Execute as our immediate boss userHR (3 rows): 
EXECUTE AS USER = 'userHR';
SELECT * FROM dbo.Employees; -- 3 rows
REVERT;
GO

-- Execute as our immediate boss userFin: 
EXECUTE AS USER = 'userFin';
SELECT * FROM dbo.Employees; -- 2 rows
REVERT;
GO

-- Execute as our Top boss userCEO (8): 
EXECUTE AS USER = 'userCEO';
SELECT * FROM dbo.Employees; -- 8 rows
REVERT;
GO

–> The results of the above 3 SELECTs looks like this:

SQL Server 2016 - Row Level Security 01

So, as you can see the three users we created resulted in different results:

– The HR & Finance users got just 3 & 2 rows, respectively.

– But the admin CEO user got all the 8 rows.
 

–> Thus, by using RLS Filter Predicate feature in SQL Server 2016 you can create your own customized Security by creating an Inline Table-Valued Function that is linked to the Security Policy for your Table.
 

–> Check Block Predicates with RLS in my [next post, Part 2].
 

–> Final Cleanup

DROP SECURITY POLICY [dbo].[ManagerFilter]
GO
DROP FUNCTION [dbo].[fn_SecurityPredicateEmployee]
GO
DROP TABLE [dbo].[Employee]
GO

DROP PROCEDURE dbo.uspGetEmployeeDetails
GO

 

Check the same demo on YouTube:


 

Check & Like my FB Page


Microsoft SQL Server 2016 Public Preview (CTP2) Available – download now

May 28, 2015 3 comments

Just got an email from Microsoft:

Microsoft SQL Server 2016 Public Preview Available – Try it Today!
 

[Register and Download CTP-2 Evaluation version (180 days)]

 

Direct download link:
SQLServer2016CTP2-x64-ENU.box
SQLServer2016CTP2-x64-ENU.exe
 

SQLServer2016CTP2
 

–> Smooth Installation with new setup-option and new features in SSMS:

Microsoft SQL Server 2016, the next major release of Microsoft’s flagship database and analytics platform, provides breakthrough performance for mission critical applications and deeper insights on your data across on-premises and cloud. The first public preview, SQL Server 2016 Community Technology Preview (CTP) 2, is now available for you to download to trial via Microsoft Azure.
 

–> Try it today for an early look at these new capabilities:

– Always Encrypted: helps protect data at rest and in motion

– Stretch Database: dynamically stretch your warm and cold transactional data to Microsoft Azure, demo video.

– Real-time Operational Analytics: our in-memory technologies are enhanced to provide real-time analytics on top of breakthrough transactional performance
 

–> Additional capabilities include:

1. PolyBase: More easily manage relational and non-relational data with the simplicity of T-SQL.

2. AlwaysOn Enhancements: Achieve even higher availability and performance of your secondaries, with up to 3 synchronous replicas, DTC support and round-robin load balancing of the secondaries.

3. Row Level Security: Enables customers to control access to data based on the characteristics of the user. Security is implemented inside the database, requiring no modifications to the application, demo video.

4. Dynamic Data Masking: Supports real-time obfuscation of data so data requesters do not get access to unauthorized data. Helps protect sensitive data even when it is not encrypted, demo video.

5. Native JSON support: Allows easy parsing and storing of JSON and exporting relational data to JSON, demo video.

6. Temporal Database support: Tracks historical data changes with temporal database support.

7. Query Data Store: Acts as a flight data recorder for a database, giving full history of query execution so DBAs can pinpoint expensive/regressed queries and tune query performance.

8. MDS enhancements: Offer enhanced server management capabilities for Master Data Services.

9. Enhanced hybrid backup to Azure: Enables faster backups to Microsoft Azure and faster restores to SQL Server in Azure Virtual Machines. Also, you can stage backups on-premises prior to uploading to Azure.
 

–> Other Benefits:

1. Enhanced in-memory performance provide up to 30x faster transactions, more than 100x faster queries than disk based relational databases and real-time operational analytics

2. New Always Encrypted technology helps protect your data at rest and in motion, on-premises and in the cloud, with master keys sitting with the application, without application changes

3. Built-in advanced analytics provide the scalability and performance benefits of building and running your advanced analytics algorithms directly in the core SQL Server transactional database

4. Business insights through rich visualizations on mobile devices with native apps for Windows, iOS and Android

5. Simplify management of relational and non-relational data with ability to query both through standard T-SQL using PolyBase technology

6. Stretch Database technology keeps more of your customer’s historical data at your fingertips by transparently stretching your warm and cold OLTP data to Microsoft Azure in a secure manner without application changes, demo video.

7. Faster hybrid backups, high availability and disaster recovery scenarios to backup and restore your on-premises databases to Microsoft Azure and place your SQL Server AlwaysOn secondaries in Azure
 

Learn more about SQL Server 2016: SQL Server 2016 Preview Page


Microsoft announced SQL Server 2016 – New features and enhancements

May 9, 2015 2 comments

On Monday, 4th May 2015 Microsoft at Ignite event announced the new version of SQL Server i.e. SQL Server 2016, which will be available for Public Preview this summer.
 

>> MSDN Blog announcement: http://blogs.technet.com/b/dataplatforminsider/archive/2015/05/04/sql-server-2016-public-preview-coming-this-summer.aspx

>> Microsoft SQL Server 2016 official page: https://www.microsoft.com/en-us/server-cloud/products/sql-server-2016
 

This version of SQL Server is going to be a major release with new features and will also overcome some limitations of SQL Server 2014.
 

SQLServer2016_02
 

-> New Performance Enhancements:

– In-memory OLTP enhancements: Greater T-SQL surface area, terabytes of memory supported and greater number of parallel CPUs, provide up to 30x faster Transactions, more than 100x faster Queries than disk-based relational databases and Real-time Operational Analytics, Demo video.

– Query Data Store: Monitor and optimize query plans with full history of query execution.

– Native JSON: Parsing & storing of JSON as relational data & exporting relational data to JSON, as it is becoming a popular format to store NoSQL/Unstructured data, Demo video.
 

–> Security Upgrades:

– Always Encrypted: Help protect data at rest and in motion with the master key residing with the application & no application changes required.

– Row Level Security: Customers can implement Row-level Security on databases to enable implementation of fine-grained access control over rows in a database table for greater control over which users can access which data, demo video.

– Dynamic Data Masking: Real-time obfuscation of data to prevent unauthorized access, demo video.
 

–> Even Higher Availability, with Enhanced AlwaysOn:

– Up to 3 synchronous replicas for auto failover across domains, for more robust High Availability and Disaster Recovery

– Round-robin load balancing of replicas

– DTC & SSIS support

– Automatic failover based on database health
 

–> Hybrid Cloud Solution:

– Stretch Database: Stretch operational tables in a secure manner into Azure for cost effective historic data availability, that lets you dynamically stretch your warm and cold transactional data to Microsoft Azure, demo video.

– Azure Data Factory integration with SSIS
 

–> Deeper Insights Across Data

– PolyBase: Manage relational & non-relational data with the simplicity of T-SQL.

– Enhanced SSIS: Designer support for previous SSIS versions and support for Power Query.

– Built-in Advanced Analytics: Bringing predictive analytic algorithms directly into SQL Server.
 

>> Check the SQL Server 2016 Datasheet here for more information on this: http://download.microsoft.com/download/F/D/3/FD33C34D-3B65-4DA9-8A9F-0B456656DE3B/SQL_Server_2016_datasheet.pdf
 

SQLServer2016_01
 

–> YouTube Videos on SQL Server 2016: