All about SQL Server Views

Advanced topics in SQL Server Views:
CHECK OPTION
ENCRYPTION
SCHEMABINDING
VIEW_METADATA

Creating Sample Data:

--DROP TABLE tempForView
CREATE TABLE tempForView(
ID INT
);
GO

INSERT INTO tempForView
SELECT 1
UNION
SELECT 2
UNION
SELECT 3;
GO

Check Option:
Check option ensures that the modification of data in the view will come up in the view again.

Example:

CREATE VIEW vw_TempWithOutCheckOption
AS
SELECT * fROM tempForView WHERE ID > 0
GO

CREATE VIEW vw_TempWithCheckOption
AS
SELECT * fROM tempForView WHERE ID > 0
WITH CHECK OPTION;
GO

Lets try to inset/Update data in view vw_TempWithOutCheckOption.

UPDATE vw_TempWithOutCheckOption SET ID = -1 WHERE ID = 1
GO

INSERT INTO vw_TempWithOutCheckOption(ID)
SELECT -2
GO

SELECT * FROM vw_TempWithOutCheckOption
GO

The above query runs and the data will be inserted/Updated in the underlying table but will not come up in the view.

Now when we try to insert update data in the view vw_TempWithCheckOption

UPDATE vw_TempWithCheckOption SET ID = -2 WHERE ID = 2
GO

INSERT INTO vw_TempWithCheckOption(ID)
SELECT -3
GO

SELECT * FROM vw_TempWithCheckOption
GO

As we are trying to insert/Update data which would not be part of the view, we are getting the error:

Msg 550, Level 16, State 1, Line 2
The attempted insert or update failed because the target view either specifies WITH CHECK OPTION or spans a view that specifies WITH CHECK OPTION and one or more rows resulting from the operation did not qualify under the CHECK OPTION constraint.
The statement has been terminated.

Encryption:

Encryption can be used when you want to hide the definition of the View.

CREATE VIEW vw_TempWithEncryption
WITH ENCRYPTION
AS
SELECT * fROM tempForView WHERE ID > 0;
GO

CREATE VIEW vw_TempWithOutEncryption
AS
SELECT * fROM tempForView WHERE ID > 0;
GO


SELECT TEXT fROM sys.syscomments WHERE ID = OBJECT_ID('vw_TempWithEncryption')
SELECT TEXT fROM sys.syscomments WHERE ID = OBJECT_ID('vw_TempWithOutEncryption')

The definition of the view that is created with encryption is not present in sys.syscomments.

SchemaBinding:
When a view is created with schema binding then it does not allow DDL modifications to the underlying tables which affect the view definition.

CREATE VIEW vw_TempWWithSchemaBinding
WITH SCHEMABINDING
AS
SELECT ID fROM dbo.tempForView WHERE ID > 0;
GO

DROP TABLE dbo.tempForView

It does not allow to drop the table dbo.tempForView as the view is referencing it and it is created with SCHEMABINDING.


Msg 3729, Level 16, State 1, Line 1
Cannot DROP TABLE ‘dbo.tempForView’ because it is being referenced by object ‘vw_TempWWithSchemaBinding’.

VIEW_METADATA:
when the applications accessing SQL Server request browse-mode metadata SQLServer basically provides the details of the TABLES from which the columns in the views are built.
But when a view is created with this option then SQL Server does not provide the base tables of the columns in the view.

More info can be found in MSDN:
http://msdn.microsoft.com/en-us/library/ms187956.aspx

When To Use LOWER/UPPER for comparing data in SQL Server – Alternatives

In SQL Server LOWER Can be used to convert uppercase/mixedcase string to lower case string. More about LOWER can be found here

Similarly, UPPER Can be used to convert lowercase/mixedcase string to upper case string. More about UPPER can be found here

Example:
[sql]
DECLARE @String VARCHAR(10)

SET @String = ‘ABcDeFGH’

SELECT @String STRING,LOWER(@String) LowerCaseSrting
[/sql]

Output:
[text]
STRING LowerCaseSrting
———- —————
ABcDeFGH abcdefgh

(1 row(s) affected)
[/text]

Comparing UpperCase and LowerCase strings
[sql]
DECLARE @String VARCHAR(10),@String1 VARCHAR(10)
SET @String = ‘ABcDeFGH’
SET @String1 = ‘abcdefgh’

IF @String = @String1
PRINT ‘Equal’
ELSE
PRINT ‘Not Equal’
[/sql]

Output:
[text]
Equal
[/text]
SQL Server by default creates databases with case insensitive collation. Hence we are getting output as Equal.

Now if we create a database in case sensitive collation and try the above query, we can notice that we get Not Equal as output.

Script:
[sql]
CREATE DATABASE testLower COLLATE SQL_Latin1_General_CP1_CS_AS
GO

USE testLower
GO

DECLARE @String VARCHAR(10),@String1 VARCHAR(10)
SET @String = ‘ABcDeFGH’
SET @String1 = ‘abcdefgh’

IF @String = @String1
PRINT ‘Equal’
ELSE
PRINT ‘Not Equal’

[/sql]

Output:
[text]
Not Equal
[/text]

The comparison will also fail when the tables are created with columns having case sensitive collation.

Script:
[sql]
CREATE TABLE TestTable(Value VARCHAR(10) COLLATE SQL_Latin1_General_CP1_CI_AS)
GO
CREATE TABLE ReferTable(Value VARCHAR(10) COLLATE SQL_Latin1_General_CP1_CI_AS)
GO

INSERT INTO TestTable(Value)
SELECT ‘lowercase’
UNION ALL
SELECT ‘LowerCase’
UNION ALL
SELECT ‘LOWERCASE’
GO

INSERT INTO ReferTable(Value)
SELECT ‘lowercase’
GO

–This query gives all three rows
–No need of lower
SELECT * FROM TestTable T JOIN ReferTable R
ON T.Value = R.Value

———————————————————
CREATE TABLE TestTable1(Value VARCHAR(10) COLLATE SQL_Latin1_General_CP1_CS_AS)
GO
CREATE TABLE ReferTable1(Value VARCHAR(10) COLLATE SQL_Latin1_General_CP1_CS_AS)
GO

INSERT INTO TestTable1(Value)
SELECT ‘lowercase’
UNION ALL
SELECT ‘LowerCase’
UNION ALL
SELECT ‘LOWERCASE’
GO

INSERT INTO ReferTable1(Value)
SELECT ‘lowercase’
GO

–This query gives only one row
SELECT * FROM TestTable1 T JOIN ReferTable1 R
ON T.Value = R.Value
[/sql]

In such scenarios as discussed above, we have to specify LOWER along with the column names to compare UpperCase with Lower Case.

[sql]
–Needs Lower to give all the tree rows
SELECT * FROM TestTable1 T JOIN ReferTable1 R
ON LOWER(T.Value) = LOWER(R.Value)
[/sql]

Observations:
LOWER Can be ignored if the database and all the table columns that are specified in the query are in CASE INSENSITIVE Collation.

Alternatives:
We can specify the CASE INSENSITIVE Collation name with the column name to compare the column using Case insensitive Collation.
[sql]
–Alternative to LOWER/UPPER
–Using CASE InSensitive Collation names in the query
SELECT * FROM TestTable1 T JOIN ReferTable1 R
ON T.Value COLLATE SQL_Latin1_General_CP1_CI_AS =
R.Value COLLATE SQL_Latin1_General_CP1_CI_AS
[/sql]

Clean Up:
[sql]
USE master
GO

DROP DATABASE testLower
[/sql]

How to get number of rows in a table without using count function

How to get number of rows in a table without using count function?

In SQL Server you can get the approximate number of rows in the table using the below sample script.

[sql]
USE AdventureWorks
GO
DECLARE @tablename AS sysname = ‘Production.Product’;

DBCC UPDATEUSAGE (0, @tablename)
WITH NO_INFOMSGS;

SELECT [ROWS]
FROM SYS.indexes AS IND
INNER JOIN
SYS.partitions AS PRT
ON IND.object_id = PRT.object_id
AND IND.index_id = PRT.index_id
WHERE IND.object_id = OBJECT_ID(@tablename)
AND IND.index_id <= 1;
[/sql]

This script uses sys.partitions to fetch the number of rows in the table.
More about sys.partitions can be found here http://msdn.microsoft.com/en-us/library/ms175012(v=sql.105).aspx

Materialized views in sql server with example

Materialized views in SQL Server are equivalant to Indexed views.

Below links have More details:
Creating indexed views in SQL Server
Advantages and disadvantages of indexed views

How to create materialized view in sql server?
Example:
[sql]
CREATE VIEW vwTest
WITH SCHEMABINDING
AS
SELECT id, name FROM Products where id > 1000

GO

–Create an index on the view.
CREATE UNIQUE CLUSTERED INDEX ix_vwTest
ON vwTest (id)
GO
[/sql]

Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.

Message:
Cannot grant deny or revoke permissions to sa dbo entity owner information_schema sys or yourself.

This message occurs when yoy try to revoke permissions for the following users:
– yourself
– sa
– dbo
– entity owner
– information_schema
– sys

Resolution:
If you wanted to grant/revoke (or) deny permissions for yourself instead of running the query using yor own login
You can alternatively
– Login as a different user and run the query.
– Ask another SQL Server user to grant/revoke (or) deny permissions to you.
– Ask your DBA to grant/revoke (or) deny permissions.

Duplicate column names are not allowed in result sets obtained through OPENQUERY and OPENROWSET. The column name “A” is a duplicate.

Error:

Msg 492, Level 16, State 1, Line 3
Duplicate column names are not allowed in result sets obtained through OPENQUERY and OPENROWSET. The column name “A” is a duplicate.

Possible Reason:
Column names being duplicate in the result set returned by OPENQUERY (or) OPENROWSET.

Example:
[sql]
SELECT 1 AS A,2 AS A
[/sql]
Executes Successfully!!!

When the same query is used in the OPENROWSET.
[sql]
SELECT * FROM OPENROWSET(‘SQLOLEDB’,
‘Server=(local);Trusted_Connection=Yes;Database=Master’,
‘SELECT 1 AS A,2 AS A’)
[/sql]

Errors Out with Msg 492, Level 16, State 1, Line 3.

Fix/Resolution:
Make sure that each and every column in the result set returned by OPENQUERY (or) OPENROWSET has a different name.
[sql]
SELECT * FROM OPENROWSET(‘SQLOLEDB’,
‘Server=(local);Trusted_Connection=Yes;Database=Master’,
‘SELECT 1 AS A,2 AS B’)
[/sql]

appropriate to SQL Server 2005,SQL Server 2008,SQL Server 2008 r2,SQL Server 2012

Range of datetime data type

Following is the range of datetime data type:

Lower range(Minimum value) :
‘1752-01-01 00:00:00.000’ January 1st 1752 12 AM

Upper range(Maximum value) :
‘9999-12-31 23:59:59.998’ December 31st 9999 12 PM (milli seconds before next day)

Queries to check the same:
This query executes successfully:
[sql]
SELECT CAST( ‘9999-12-31 23:59:59.998’ AS DATETIME)
[/sql]

This query fails:
[sql]
SELECT CAST( ‘9999-12-31 23:59:59.999’ AS DATETIME)
[/sql]

This query executes successfully:
[sql]
SELECT CAST( ‘1753-01-01 00:00:00.000’ AS DATETIME)
[/sql]

This query fails:
[sql]
SELECT CAST( ‘1752-12-31 23:59:59.999’ AS DATETIME)
[/sql]

Applicable to: SQL Server 2005, SQL Server 2008,SQL Server 2008 r2,SQL Server 2012

Group By Month, Year with example

In order to group by month you can use the SQL Server in built funtion Month().
[sql]
GROUP BY MONTH([datetimecolumn])
[/sql]
TO group data by year you can use the in built funtion YEAR().
[sql]
GROUP BY YEAR([datetimecolumn])
[/sql]
In order to group by month and year you can use bith YEAR() and MONTH().
[sql]
GROUP BY YEAR([datetimecolumn])
[/sql]

Example code:
[sql]
CREATE TABLE #Sales
(
Name VARCHAR (100),
SalesDateTime DATETIME
)

GO
INSERT INTO #Sales
SELECT ‘Product1’,
‘2010-04-01 00:00:00.000’
UNION ALL
SELECT ‘Product2’,
‘2010-04-02 00:00:00.000’
UNION ALL
SELECT ‘Product3’,
‘2011-04-02 00:00:00.000’
UNION ALL
SELECT ‘Product4’,
‘2011-04-03 00:00:00.000’
UNION ALL
SELECT ‘Product5’,
‘2011-04-03 00:00:00.000’
UNION ALL
SELECT ‘Product1’,
‘2012-04-30 00:00:00.000’
UNION ALL
SELECT ‘Product1’,
‘2012-04-30 00:00:00.000’
UNION ALL
SELECT ‘Product1’,
‘2012-05-02 00:00:00.000’
UNION ALL
SELECT ‘Product5’,
‘2012-05-02 00:00:00.000’
UNION ALL
SELECT ‘Product5’,
‘2012-05-02 00:00:00.000’

GO
–GROUP BY Month
SELECT count(*) AS SalesCount, MONTH(SalesDateTime) Month
FROM #Sales
GROUP BY MONTH(SalesDateTime)

–GROUP BY YEAR
SELECT count(*) AS SalesCount, YEAR(SalesDateTime) YEAR
FROM #Sales
GROUP BY YEAR(SalesDateTime)

–GROUP BY Month and Year
SELECT count(*) AS SalesCount, YEAR(SalesDateTime) YEAR,MONTH(SalesDateTime) Month
FROM #Sales
GROUP BY YEAR(SalesDateTime),MONTH(SalesDateTime)

GO
DROP TABLE #Sales
[/sql]

sql server 2005,2008,2008 r2,2012

Group by Day – With Examples

How to Group by Day in sql server?

Grouping By Day Of month:
In order to group the data by day you can use sql server in built DAY() funtion.

Grouping By Day Of week:
For this you can use DATEPART(weekday,[date column])

Grouping By week:
For this you can use DATEPART(week,[date column])

Grouping By DAY of Year:
For this you can use DATEPART(dayofyear,[date column])

Let us suppose the column which contains date/datetime values is solddatetime.

To group by day of month you can use:
[sql]
GROUP BY DAY(SalesDateTime)
[/sql]

To group by Day of week you can use:
[sql]
GROUP BY DATEPART(weekday,SalesDateTime)
[/sql]

To group by week you can use:
[sql]
GROUP BY DATEPART(week,SalesDateTime)
[/sql]

To group by Day of year you can use:
[sql]
GROUP BY DATEPART(dayofyear,SalesDateTime)
[/sql]

Complete example:
[sql]
CREATE TABLE #Sales
(
Name VARCHAR (100),
SalesDateTime DATETIME
)

GO
INSERT INTO #Sales
SELECT ‘Product1’,
‘2012-04-01 00:00:00.000’
UNION ALL
SELECT ‘Product2’,
‘2012-04-02 00:00:00.000’
UNION ALL
SELECT ‘Product3’,
‘2012-04-02 00:00:00.000’
UNION ALL
SELECT ‘Product4’,
‘2012-04-03 00:00:00.000’
UNION ALL
SELECT ‘Product5’,
‘2012-04-03 00:00:00.000’
UNION ALL
SELECT ‘Product1’,
‘2012-04-30 00:00:00.000’
UNION ALL
SELECT ‘Product1’,
‘2012-04-30 00:00:00.000’
UNION ALL
SELECT ‘Product1’,
‘2012-05-02 00:00:00.000’
UNION ALL
SELECT ‘Product5’,
‘2012-05-02 00:00:00.000’
UNION ALL
SELECT ‘Product5’,
‘2012-05-02 00:00:00.000’

GO
–GROUP BY DAY of Month
SELECT count(*) AS SalesCount, DAY(SalesDateTime) Day
FROM #Sales
GROUP BY DAY(SalesDateTime)

–GROUP BY DAY of Week
SELECT count(*) AS SalesCount, DATEPART(weekday,SalesDateTime) Day
FROM #Sales
GROUP BY DATEPART(weekday,SalesDateTime)

–GROUP BY Week
SELECT count(*) AS SalesCount, DATEPART(week,SalesDateTime) Day
FROM #Sales
GROUP BY DATEPART(week,SalesDateTime)

–GROUP BY DAY of Year
SELECT count(*) AS SalesCount, DATEPART(dayofyear,SalesDateTime) Day
FROM #Sales
GROUP BY DATEPART(dayofyear,SalesDateTime)

GO
DROP TABLE #Sales
[/sql]