Archive
SQL Basics – Working with VIEWs in SQL Server
Views in SQL Server and other RDBMSs are simply Virtual Tables or Stored Queries. Views are like tables, contains rows and columns, but do not store any data within. Instead they use the Query that is defined to create the view to show data from one or more tables.
–> A view can be used for:
1. Simplifying a complex query, give it a simple name, and use it like a table.
2. Providing security by restricting the table access and showing only selected Columns and Rows via Views.
3. Providing compatibility with other client systems that cannot be changed.
–> Now let’s see how Views helps with above points:
Point #1: Consider Query below, it will be difficult and time consuming to write the same query every time. Also due to human error at times you may not be able to get same or desired results, because you can commit mistake or forget something while writing the same logic.
USE [AdventureWorks2014] GO SELECT P.BusinessEntityID AS EmpID ,P.Title ,CONCAT(P.FirstName, ' ', P.MiddleName, ' ', P.LastName) AS EmployeeName ,P.Suffix ,E.BirthDate ,CASE WHEN E.Gender = 'M' THEN 'Male' ELSE 'Female' END as Gender ,IIF(E.MaritalStatus = 'S', 'Single', 'Married') as MaritalStatus FROM Person.Person P JOIN [HumanResources].[Employee] E ON E.BusinessEntityID = P.BusinessEntityID
… here we have Joined 2 tables and selected only required columns. You will also notice that we have changed the column names (alias), and created calculated columns, like EmployeeName, Gender & MaritalStatus.
So rather than writing this query every time, its better to store this query as a View, like below:
CREATE VIEW dbo.vwPersonEmployee AS SELECT P.BusinessEntityID AS EmpID ,P.Title ,CONCAT(P.FirstName, ' ', P.MiddleName, ' ', P.LastName) AS EmployeeName ,P.Suffix ,E.BirthDate ,CASE WHEN E.Gender = 'M' THEN 'Male' ELSE 'Female' END as Gender ,IIF(E.MaritalStatus = 'S', 'Single', 'Married') as MaritalStatus FROM Person.Person P JOIN [HumanResources].[Employee] E ON E.BusinessEntityID = P.BusinessEntityID GO
… and simply execute the view instead of the query now onwards, like:
SELECT * FROM dbo.vwPersonEmployee
Point #2: The above View uses 2 tables Person.Person & HumanResources.Employee. Now if you want a user to have restricted access to these 2 tables, but also want the user to query View to get desired and restricted data, then you can GRANT access only to the View, like:
CREATE USER userView WITHOUT LOGIN; GRANT SELECT ON dbo.vwPersonEmployee TO userView; GO EXECUTE AS USER = 'userView'; SELECT * FROM dbo.vwPersonEmployee -- Displays View data SELECT * FROM Person.Person -- ERROR: The SELECT permission was denied on the object SELECT * FROM HumanResources.Employee -- ERROR: The SELECT permission was denied on the object REVERT; GO DROP USER userView GO
… here when the user executes the View he can see the data, but with only selected columns. But if he tries to use tables, he will get error.
Point #3: Now let’s say a client application which was getting data from an old table, let’s say dbo.Person, with following columns: PersonID, PersonFirstName, PersonLastName. Now on the new DB system the table is replaced by a new table Person.Person with different column names. This will make the system unusable and unstable.
But with the use of Views we can fill the gap, by creating a new View with name dbo.Person on top of Person.Person, and aliasing new columns with old column names, like:
CREATE VIEW dbo.Person AS SELECT BusinessEntityID as PersonID ,FirstName as PersonFirstName ,LastName as PersonLastName FROM Person.Person GO
… so by this way the client application can talk to the new table by hitting the View instead of the Table.
–> Dropping/Deleting Views:
DROP VIEW dbo.vwPersonEmployee DROP VIEW dbo.Person
XACT_ABORT with TRANSACTIONS in SQL Server
SQL Server by default does not ROLLBACK a Transaction if there is error anywhere in the code inside a BEGIN TRANSACTION & COMMIT TRANSACTION block. It only skips the statement that causes the error and moves ahead.
To allow a transaction to complete entirely or fail entirely you can use the TRY-CATCH feature with ROLLBACK statement or the SET XACT_ABORT statement.
By default the SET XACT_ABORT is OFF. There ar very few cases where the T-SQL statement that raised exception are rolled back and the transaction continues processing. Depending upon the severity of the error, the entire transaction may be rolled back even when SET XACT_ABORT is OFF.
But When SET XACT_ABORT is ON, if a T-SQL statement raises an exception, then the entire transaction is terminated and rolled back.
–> Here let’s check how we can use XACT_ABORT with an example:
-- Create a test tabel and insert some records: CREATE TABLE Tab (x INT NOT NULL PRIMARY KEY) INSERT INTO Tab VALUES (1) INSERT INTO Tab VALUES (2) INSERT INTO Tab VALUES (3) GO -- ================================= -- Check with XACT_ABORT OFF option: -- ================================= SET XACT_ABORT OFF; -- By default it is OFF BEGIN TRANSACTION INSERT INTO Tab VALUES (4) INSERT INTO Tab VALUES (4) -- Statement fails but transaction is committed. INSERT INTO Tab VALUES (5) COMMIT TRANSACTION GO /* -- On message pane: (1 row(s) affected) Msg 2627, Level 14, State 1, Line 5 Violation of PRIMARY KEY constraint 'PK__Tab__3BD019E56991A7CB'. Cannot insert duplicate key in object 'dbo.Tab'. The duplicate key value is (4). The statement has been terminated. (1 row(s) affected) */ SELECT * FROM Tab -- List records: 1,2,3,4,5 GO -- ================================ -- Check with XACT_ABORT ON option: -- ================================ SET XACT_ABORT ON BEGIN TRANSACTION INSERT INTO Tab VALUES (6) -- Inserts 6, but the transaction is rollbacked in next step. INSERT INTO Tab VALUES (6) -- Statement fails and rollbacks the entire transaction. INSERT INTO Tab VALUES (7) -- Statement skipped as transaction is rollbacked at previous statement. COMMIT TRANSACTION SET XACT_ABORT OFF GO /* -- On message pane: (1 row(s) affected) Msg 2627, Level 14, State 1, Line 5 Violation of PRIMARY KEY constraint 'PK__Tab__3BD019E56991A7CB'. Cannot insert duplicate key in object 'dbo.Tab'. The duplicate key value is (6). */ SELECT * FROM Tab -- Still list records: 1,2,3,4,5 GO -- Final cleanup DROP TABLE Tab GO
We can also use TRY-CATCH constructs that helps in handling transaction and can be used instead of XACT_ABORT statement. Check here how we can use them.
SQL Trivia – Identify & Delete Duplicate records from a table
I see a lot of questions/posts about dealing with duplicate records in many SQL Server forums. Many of these questions are asked in SQL Server Interviews and many developers starting their carrier in database programming find it challenging to deal with. Here we will see how we can deal with such records.
Duplicate data is one of the biggest pain points in our IT industry, which various projects have to deal with. Whatever state-of-art technology and best practices followed, the big ERP, CRM, SCM and other inventory based database management projects ends up in having duplicate & redundant data. Duplicate data keeps on increasing by manual entries and automated data loads. Various data leads getting pumped into system’s databases without proper deduping & data cleansing leads to redundant data and thus duplicated record-sets.
Data cleansing requires regular exercise of identifying duplicates, validating and removing them. To minimize these type of scenarios various checks and filters should also be applied before loading new leads into the system.
–> Lets check this by a simple exercise how we can identify & remove duplicate data from a table:
1. Insert some sample records from Person.Contact table of [AdventureWorks] database:
USE [AdventureWorks] GO SELECT TOP 10 ContactID, FirstName, LastName, EmailAddress, Phone INTO DupContacts FROM Person.Contact SELECT * FROM DupContacts
2. Insert some duplicate records from the same list inserted above:
INSERT INTO DupContacts SELECT TOP 50 PERCENT FirstName, LastName, EmailAddress, Phone from DupContacts SELECT * FROM DupContacts
3. Insert some more duplicate records from the same list inserted above.
INSERT INTO DupContacts SELECT TOP 20 PERCENT FirstName, LastName, EmailAddress, Phone from DupContacts SELECT * FROM DupContacts
–> Identify Duplicate records & delete them
Method #1: by using ROW_NUMBER() function:
;WITH dup as ( SELECT ContactID, FirstName, LastName, EmailAddress, Phone, ROW_NUMBER() OVER(PARTITION BY FirstName, LastName ORDER BY ContactID) AS NumOfDups FROM DupContacts) SELECT * FROM dup WHERE NumOfDups > 1 ORDER BY ContactID
-- Remove/Delete duplicate records: ;WITH dup as ( SELECT ContactID, FirstName, LastName, EmailAddress, Phone, ROW_NUMBER() OVER(PARTITION BY FirstName, LastName ORDER BY ContactID) AS NumOfDups FROM DupContacts) DELETE FROM dup WHERE NumOfDups > 1 SELECT * FROM DupContacts
Method #2: by using SELF-JOIN:
SELECT DISTINCT a.ContactID, a.FirstName, a.LastName, a.EmailAddress, a.Phone FROM DupContacts a JOIN DupContacts b ON a.FirstName = b.FirstName AND a.LastName = b.LastName AND a.ContactID > b.ContactID
-- Remove/Delete duplicate records: DELETE a FROM DupContacts a JOIN DupContacts b ON a.FirstName = b.FirstName AND a.LastName = b.LastName AND a.ContactID > b.ContactID SELECT * FROM DupContacts
Method #3: by using AGGREGATES & Sub-QUERY:
SELECT * FROM DupContacts WHERE ContactID NOT IN (SELECT MIN(ContactID) FROM DupContacts GROUP BY FirstName, LastName)
-- Remove/Delete duplicate records: DELETE FROM DupContacts WHERE ContactID NOT IN (SELECT MIN(ContactID) FROM DupContacts GROUP BY FirstName, LastName) SELECT * FROM DupContacts
–> Final Cleanup
DROP TABLE DupContacts
Check the same demo here:
UPDATE statement with new .WRITE Clause – SQL Server
As per MS BOL the new .WRITE clause of the UPDATE DML statement enables partial or full updates and high performance appends to varchar(max), nvarchar(max) and varbinary(max) data type columns.
The UPDATE statement is logged; however, partial updates to large value data types using the .WRITE clause are minimally logged.
Syntax: .WRITE ( expression, @Offset , @Length )
Usage: The string specified in the expression param is replaced by the number of characters specified in
@Length param starting from the position mentioned in @Offset param.
Let’s check this with an example mentioned below: The “Senior” character set is replaced by the 3 length character “Sr.” starting from the 18th character.
-- Create a table containing a VARCHAR(MAX), NVARCHAR(MAX) or VARBINARY(MAX) column:
CREATE TABLE CheckWrite (empID INT, eName VARCHAR(50), descr VARCHAR(MAX))
-- Insert test data in the table:
INSERT INTO CheckWrite
SELECT 101, 'Manoj Pandey', 'Manoj Pandey is a Sr. SQL Server developer and CRM analyst. He likes Photography & travelling.'
-- Check inserted record before UPDATE:
SELECT * FROM CheckWrite
-- Now UPDATE the descr column by using .WRITE clause:
UPDATE CheckWrite
SET descr .WRITE('Senior', 18, 3)
WHERE empID = 101
-- Check the updated result:
SELECT * FROM CheckWrite
-- Final cleanup
DROP TABLE CheckWrite
Note: The .WRITE clause cannot be used to update a NULL column or set the value of column_name to NULL.
>> Check & Subscribe my [YouTube videos] on SQL Server.
Stored Procedures vs Functions (Difference between SP & UDF) – SQL Server
Stored Procedures can contain a single SQL statement or a group of SQL statements with data flow control logic containing IF-ELSE, WHILE loop constructs, TRY-CATCH, transactions, etc.
SPs are used to return one or many result-sets to its calling application.
On the other hand Functions or UDFs can contain single or multiple SQL statements depending on its type. A Scalar UDF & Inline UDF can only have a single SELECT statement. And a Multi-Statement UDF can contain a body with multiple SQL statements including SELECTS, IF-ELSE, WHILE loops and DMLs but limited to manipulating table variables only.
UDFs return a single Scalar value or a Table variable to the calling SELECT statement.
Following are some common differences between an SP & a UDF:
–> Stored Procedures (SP):
– Can be used to read and modify data.
– To run an SP Execute or Exec is used, cannot be used with SELECT statement.
– Cannot JOIN a SP in a SELECT statement.
– Can use Table Variables as well as Temporary Tables inside an SP.
– Can create and use Dynamic SQL.
– Can use transactions inside (BEGIN TRANSACTION, COMMIT, ROLLBACK) an SP.
– Can use used with XML FOR clause.
– Can use a UDF inside a SP in SELECT statement.
– Cannot be used to create constraints while creating a table.
– Can execute all kinds of functions, be it deterministic or non-deterministic.
–> Functions (UDF):
– Can only read data, cannot modify the database.
– Can only be used with SELECT statement, JOINS & APPLY (CROSS & OUTER).
– Can JOIN a UDF in a SELECT statement.
– Cannot use a Temporary Table, only Table Variables can be used.
– Cannot use a Dynamic SQL inside a UDF.
– Cannot use transactions inside a UDF.
– Cannot be used with XML FOR clause.
– Cannot execute an SP inside a UDF.
– Can be used to create Constraints while creating a table.
– Cannot execute some non-deterministic built-in functions, like GETDATE().
More about “User Defined Functions” (UDFs) [check here].
>> Check & Subscribe my [YouTube videos] on SQL Server.












