- ZoomIt: ZoomIt is a screen zoom and annotation tool for technical presentations that include application demonstrations.
- Devart SQL Complete: Code completion, refactoring and formatting tool.
- sp_whoisactive: sp_whoisactive is a comprehensive activity monitoring stored procedure that works for all versions of SQL Server from 2005 through 2017.
- sp_SQLskills_helpindex: Tool to get index information. sp_helpindex displays limited information. This tool displays lot of information like included columns, filters, etc.
Showing posts with label t-sql. Show all posts
Showing posts with label t-sql. Show all posts
Friday, March 8, 2019
Useful tools
Monday, January 22, 2018
Difference between Table Variables, Temporary Tables (Hash Tables) and Temporal Tables
Table Variables
- Table variable is a special data type that can be used to store a result set for processing at a later time.
- Table variable is primarily used for temporary storage of a set of rows returned as the result set of a table-valued function.
- Functions and variables can be declared to be of type table.
- Table variables can be used in functions, stored procedures, and batches.
- To declare variables of type table, use DECLARE @local_variable
- A table variable behaves like a local variable. It has a well-defined scope. This is the function, stored procedure, or batch that it is declared in.
Example:
DECLARE @myTable TABLE
(
Id INT PRIMARY KEY,
FirstName VARCHAR(100) UNIQUE,
LastName VARCHAR(100) NOT NULL
)
INSERT INTO @myTable(Id, FirstName, LastName) VALUES (1,'A','A')
INSERT INTO @myTable(Id, FirstName, LastName) VALUES (2,'B',NULL) --Fail
INSERT INTO @myTable(Id, FirstName, LastName) VALUES (3,'A','A') --Fail
SELECT * from @myTable
SELECT * INTO @This_Will_Not_Work FROM @myTable
Only constraints allowed on the table variables are:
- Primary Key
- UNIQUE
- NULL
Further, SELECT * INTO will not work
Temporary Tables (Hash Tables)
There are two types of temporary tables; one is local and the other is global.
Local Temporary Tables
Local temporary tables are the tables stored in tempdb. Local temporary tables are temporary tables that are available only to the session that created them. These tables are automatically destroyed at the termination of the procedure or session. They are specified with the prefix #, for example #table_name and these temp tables can be created with the same name in multiple windows.
Example:
--Local
temporary table
CREATE TABLE
#myLocalTable
(
Id INT PRIMARY KEY,
FirstName VARCHAR(100) UNIQUE,
LastName VARCHAR(100) NOT NULL DEFAULT('')
)
INSERT INTO
#myLocalTable(Id, FirstName, LastName) VALUES (1,'A','A')
INSERT INTO #myLocalTable(Id, FirstName) VALUES (2,'B') --Default LastName
Global Temporary Tables
Global temporary tables are also stored in tempdb. Global temporary tables are temporary tables that are available to all sessions and all users. They are dropped automatically when the last session using the temporary table has completed. They are specified with the prefix #, for example ##table_name.
Example:
--Global
temporary table
CREATE TABLE
##myLocalTable
(
Id INT PRIMARY KEY,
FirstName VARCHAR(100) UNIQUE,
LastName VARCHAR(100) NOT NULL DEFAULT('')
)
INSERT INTO
##myLocalTable(Id, FirstName, LastName) VALUES (1,'A','A')
INSERT INTO
##myLocalTable(Id, FirstName) VALUES (2,'B') --Default LastName
SQL Server 2016 introduced support for system-versioned temporal tables as a database feature that brings built-in support for providing information about data stored in the table at any point in time rather than only the data that is correct at the current moment in time.
Example:
Example:
CREATE TABLE dbo.TemporalTable
(
ID INT NOT NULL PRIMARY KEY CLUSTERED,
FirstName VARCHAR(100),
LastName VARCHAR(100),
ValidFrom datetime2 GENERATED ALWAYS AS ROW START,
ValidTo datetime2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.TemporalTableHistory));
--Insert
a record
INSERT INTO dbo.TemporalTable(ID, FirstName, LastName) VALUES(1,'Akash','Agrawal')
--Current
table will have one record. Notice the ValidFrom and ValidTo columns
SELECT * FROM dbo.TemporalTable
SELECT * FROM dbo.TemporalTableHistory --zero records
--Now,
update record in the table
UPDATE TemporalTable
SET FirstName = 'Aakash'
WHERE ID = 1
--Data
will be updated in current table. Notice the ValidFrom and ValidTo columns
SELECT * FROM dbo.TemporalTable
--History
table will have one record with ValidFrom and ValidTo columns populated.
SELECT * FROM dbo.TemporalTableHistory
--Update
again
UPDATE TemporalTable
SET FirstName = 'Aakaash'
WHERE ID = 1
--Notice
multiple rows in History table
SELECT * FROM dbo.TemporalTable
SELECT * FROM dbo.TemporalTableHistory
--How to
query History data
SELECT *
FROM dbo.TemporalTable
FOR SYSTEM_TIME BETWEEN '2018-01-22 08:12:26.2254807' AND '2018-01-22
08:14:44.7907589'
SELECT *
FROM dbo.TemporalTable
FOR SYSTEM_TIME AS OF '2018-01-22
08:14:44.7907589'
SELECT *
FROM dbo.TemporalTable
FOR SYSTEM_TIME FROM '2018-01-22 08:12:26.2254807' TO '2018-01-22
08:14:44.7907589'
SELECT *
FROM dbo.TemporalTable
FOR SYSTEM_TIME CONTAINED IN('2018-01-22
08:12:26.2254807' , '2018-01-22 08:15:44.7907589')
SELECT *
FROM dbo.TemporalTable
FOR SYSTEM_TIME ALL
ORDER BY ValidFrom
Tuesday, May 2, 2017
Use of functions on indexed columns in predicates
Use of functions on indexed columns which are used in predicates results in index not getting used for seek operation.
For example:
Now, what if we rewrite this query without the use of LEFT function as below:
Functions on indexed column used in predicates makes them non-sargable and impacts performance.
For example:
Use tempdb
set nocount on
go
IF OBJECT_ID(N'Customers', N'U') IS NOT NULL
DROP TABLE dbo.Customers;
CREATE TABLE dbo.Customers (
customer_nbr INT NOT NULL PRIMARY KEY,
customer_name VARCHAR(35) NOT NULL);
CREATE NONCLUSTERED INDEX
ix_customers
ON dbo.Customers(customer_name);
INSERT dbo.Customers VALUES(1, 'Joe');
INSERT dbo.Customers VALUES(2, 'Leo');
INSERT dbo.Customers VALUES(3, 'Dave');
INSERT dbo.Customers VALUES(4, 'Lenny');
INSERT dbo.Customers VALUES(5, 'Larry');
INSERT dbo.Customers VALUES(6, 'Lefty');
INSERT dbo.Customers VALUES(7, 'Lemur');
GO
If I want to write a query on this table to get all the customers whose first name starts with 'L'.
SELECT customer_name
FROM dbo.Customers
WHERE LEFT(customer_name, 1) = 'L';
Looking at the execution plan for above query. We can see index scan in here and not seek:
Now, what if we rewrite this query without the use of LEFT function as below:
SELECT customer_name
FROM dbo.Customers
WHERE customer_name LIKE 'L%';
Looking at the execution plan for above query shows us index seek and the output of query is same as before.
Functions on indexed column used in predicates makes them non-sargable and impacts performance.
Reference:
https://sqlbits.com/Sessions/Event14/Common_TSQL_Mistakes
Friday, March 10, 2017
SQL Server important links
- Joins
- Indexes
- Index seek, scan, lookup and others in execution plan
- Temporary tables vs table variables
- SARGable expressions
Tuesday, January 24, 2017
Store and retrieve data into XML from table in SQL Server
The aim of this post is to store data in a table in the form of XML along with schema, and to retrieve the same from XML in a tabular structure.
Let us take an example of a table say Employee:
Let us take an example of a table say Employee:
CREATE TABLE Employee
(
ID INT,
FName VARCHAR(200),
LNAME VARCHAR(200),
Salary FLOAT
);
INSERT INTO Employee(ID, FName, LName, Salary)
VALUES(1,'A','B',10.1),
(2,'C','D',12.123),
(3,'E','F',123.13)
DECLARE
@xml XML
SELECT
@xml = (
SELECT
ID,
FName,
LName,
Salary
FROM
Employee
FOR XML AUTO, ELEMENTS, XMLSCHEMA('AnySchema'), ROOT('Root');
)
SELECT
@xml
This is how Table can be stored in XML format along with schema. If you see the output XML, it will have two portions, one with schema and another with actual data.
Below, is how we can get back the data from XML into tabular structure.
Below, is how we can get back the data from XML into tabular structure.
DECLARE
@XSD XML, @sql VARCHAR(MAX), @TableName VARCHAR(100)
SET
@XSD = (SELECT
x.query('.')
FROM @XML.nodes('/Root/*[1]') a (x))
SELECT
@XML = (SELECT
CAST(STUFF(
CAST(@XML.query('*[1]/*') AS VARCHAR(MAX))
,
1
,
CHARINDEX(
'</xsd:schema>'
,
CAST(@XML.query('*[1]/*') AS VARCHAR(MAX))
)
+ 12
,
''
)
AS XML)
FOR
XML RAW ('Root'))
SELECT
@XML = CAST(REPLACE(CAST(@XML AS VARCHAR(MAX)), '
xmlns="AnySchema"', '') AS XML)
SELECT
@TableName =
a.x.value('@name', 'varchar(100)')
FROM
@XSD.nodes('/*/*') a (x)
SELECT
@XSD = (SELECT
a.x.query('.')
FROM
@XSD.nodes('/*/*[2]/*/*') a (x))
SELECT
@XSD = CAST(REPLACE(CAST(@XSD AS VARCHAR(MAX)), 'p1:', '') AS XML)
IF
@XSD IS NULL
BEGIN
SELECT
'XML Schema was
not specified'
RETURN
END
IF EXISTS (SELECT
1
FROM
Tempdb..sysobjects
WHERE id = OBJECT_ID('Tempdb..#TableDefinition'))
DROP TABLE #TableDefinition
CREATE TABLE #TableDefinition
(
ID INT IDENTITY(1,1),
ColumnName VARCHAR(255),
ColumnDataType1 VARCHAR(255),
ColumnDataType2 VARCHAR(255),
ColumnDataType2Length VARCHAR(255),
hasLength INT
)
INSERT INTO #TableDefinition
SELECT
a.x.value('@name', 'varchar(100)')
ColumnName
,REPLACE(CAST(a.x.value('@type', 'sysname') AS VARCHAR(100)), 'sqltypes:', '') ColumnDataType1
,REPLACE(CAST(a.x.value('*[1]/*[1]/@base', 'sysname') AS VARCHAR(100)), 'sqltypes:', '') ColumnDataType2
,REPLACE(CAST(a.x.value('*[1]/*[1]/*[1]/@value', 'sysname') AS VARCHAR(100)), 'sqltypes:', '') ColumnDataType2Length
,0
AS hasLength
FROM
@XSD.nodes('/*/*') a (x)
UPDATE
#TableDefinition
SET hasLength =
1
,ColumnDataType2Length
=
CASE
WHEN
ColumnDataType2 IN ('numeric', 'decimal') THEN RTRIM(ColumnDataType2Length) + ',10'
ELSE
ColumnDataType2Length
END
WHERE
ColumnDataType2Length IS NOT NULL
DECLARE
@TableDefinition VARCHAR(MAX)
SET
@TableDefinition = (SELECT
CAST(CASE
WHEN
hasLength = 1 THEN
ColumnName + ' '
+ ColumnDataType2 +
'(' +
ColumnDataType2Length + '),'
ELSE
ColumnName + ' '
+ ColumnDataType1 +
','
END
AS VARCHAR(MAX))
FROM
#TableDefinition a
FOR XML PATH (''))
SELECT
@TableDefinition =
SUBSTRING(@TableDefinition, 0, LEN(@TableDefinition))
IF EXISTS (SELECT
1
FROM
Tempdb..sysobjects
WHERE id = OBJECT_ID('Tempdb..#XML'))
DROP TABLE #XML
SELECT
@XML AS
XMLDATA INTO #XML
SELECT
@sql =
' DECLARE @handle
INT, @PrepareXMLStatus INT, @XML2 XML
SET @XML2 = (SELECT XMLDATA FROM #XML);
EXEC @PrepareXMLStatus =
sp_xml_preparedocument @handle OUTPUT, @XML2;
SELECT *
FROM OPENXML(@handle, ''/Root/' + @TableName + ''', 2)
WITH (' + @TableDefinition + ')
EXEC sp_xml_removedocument @handle;'
EXEC (@sql)
Subscribe to:
Posts (Atom)