<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>sequences &#8211; SQLpowered.com</title>
	<atom:link href="https://sqlpowered.com/tag/sequences/feed/" rel="self" type="application/rss+xml" />
	<link>https://sqlpowered.com</link>
	<description>SQL Server + BI</description>
	<lastBuildDate>Sat, 13 Jun 2020 07:15:57 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://sqlpowered.com/wp-content/uploads/2020/07/FavIcon-e1594067873682-99x100.png</url>
	<title>sequences &#8211; SQLpowered.com</title>
	<link>https://sqlpowered.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Sequences</title>
		<link>https://sqlpowered.com/sequences-introduction/</link>
					<comments>https://sqlpowered.com/sequences-introduction/#respond</comments>
		
		<dc:creator><![CDATA[Jan Dvořák]]></dc:creator>
		<pubDate>Thu, 16 Jun 2016 07:25:46 +0000</pubDate>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[sequences]]></category>
		<guid isPermaLink="false">https://sqlpowered.com/?p=2029</guid>

					<description><![CDATA[Sequences come new with the SQL Server 2012 and finally include ANSI standard for generating numerical sequences, which had been missing in the SQL Server until now. Neither IDENTITY nor other various custom solutions were fully able to replace it. Sequences are independent objects, which we can created on the...]]></description>
										<content:encoded><![CDATA[<p>Sequences come new with the SQL Server 2012 and finally include ANSI standard for generating numerical sequences, which had been missing in the SQL Server until now. Neither IDENTITY nor other various custom solutions were fully able to replace it. Sequences are independent objects, which we can created on the level of a database scheme and are neither assigned to a table nor to a column, as was the case with IDENTITY up until now. Their main purpose is to generate numerical values in ascending or descending order and at intervals defined upon their creation. For generating new values, the sequences are referenced directly by means of an application or database code. The article will closely show you how sequences are created, which set up the sequences have and how to obtain new values. We will also think about whether they can be considered as a full-fledged replacement of IDENTITY from the database developer’s point of view and what it would mean to replace it by sequences in the existing IDENTITY database, in this case.<br />
<span id="more-2029"></span></p>
<p>[toc]</p>
<h3>1. Creating Sequences</h3>
<p>Sequences are created similarly as other database objects with using of the commands:  CREATE SEQUENCE and are removed with the commands: DROP SEQUENCE. The same is true for their change, which is done with ALTER SEQUENCE.</p>
<p>The syntax of the CREATE SEQUENCE command  is as follows:</p>
<pre class="lang:tsql highlight:0 decode:true">CREATE SEQUENCE [schema_name . ] sequence_name
    [ AS [ built_in_integer_type | user-defined_integer_type ] ]
    [ START WITH &lt;constant&gt; ]
    [ INCREMENT BY &lt;constant&gt; ]
    [ { MINVALUE [ &lt;constant&gt; ] } | { NO MINVALUE } ]
    [ { MAXVALUE [ &lt;constant&gt; ] } | { NO MAXVALUE } ]
    [ CYCLE | { NO CYCLE } ]
    [ { CACHE [ &lt;constant&gt; ] } | { NO CACHE } ]
    [ ; ]</pre>
<p><strong>[schema_name].[sequence_name]</strong></p>
<ul>
<li>The same rules apply for the name of a sequence as for other database objects. Sequences always belong to only one database scheme and their name has to be unique within the scheme. Since it is dealing with independent database objects, we can apply security settings equal to the scheme compared to IDENTITY, where no explicit assignment of rights was possible.</li>
</ul>
<p><strong>AS [ built_in_integer_type | user-defined_integer_type ]</strong></p>
<ul>
<li>Each sequence has its own system or user data type and it can only deal with some of these numerical data types:
<ul>
<li><strong>tinyint</strong> &#8211; from 0 to 255</li>
<li><strong>smallint</strong> &#8211; from -32,768 to 32,767</li>
<li><strong>int</strong> &#8211; from -2,147,483,648 to 2,147,483,647</li>
<li><strong>bigint</strong> &#8211; from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807</li>
<li><strong>decimal</strong> and <strong>numeric</strong>, but only with zero count tenths decimal places</li>
</ul>
</li>
<li>User data types established on the above mentioned system types.</li>
<li>The initial data type is bigint. It is good to keep this is mind when creating sequences because in most cases the range of this data type will not be necessary and it is more beneficial to select the lowest data type possible.</li>
</ul>
<p><strong>START WITH &lt;constant&gt;</strong></p>
<ul>
<li>Determines this first value, which the sequence will return. It is an extremely important setting because when it is not used, the first returned value will be the minimum or maximum value of the used data type according to whether it is dealing with an ascending or descending sequence. The value must obviously be within the range of the selected data type.</li>
</ul>
<p><strong>INCREMENT BY &lt;constant&gt;</strong></p>
<ul>
<li>The value determining the size of the increment or decrement upon every calling of the function NEXT VALUE FOR, which obtains another value from the sequence. The value cannot be 0 and the initial setting is 1. The value can also be negative, the same as for IDENTITY.</li>
</ul>
<p><strong>MINVALUE &lt;constant&gt; | NO MINVALUE</strong></p>
<ul>
<li>Determines the minimum value, which will be generated by the given sequence. If it is not determined, the minimum value is always the lowest value of the used data type, possibly 0 for tinyint.</li>
</ul>
<p><strong>MAXVALUE &lt;constant&gt; | NO MAXVALUE</strong></p>
<ul>
<li>Determines the top limit of the sequence. If it is not set, the top limit is the maximum value of the data type.</li>
</ul>
<p><strong>CYCLE | NO CYCLE</strong></p>
<ul>
<li>This characteristic determines whether the sequence should again start generating from the beginning once it has reached the maximum value for an ascending sequence or a minimum value for a descending sequence. The initial setting is NO CYCLE and upon reaching the limit maximum value, an exception is generated. We cannot forget that if a renewal of the cycle takes place, the sequence re-starts from the minimum or maximum values, not from the START WITH values.</li>
</ul>
<p><strong>CACHE [&lt;constant&gt; ] | NO CACHE</strong></p>
<ul>
<li>Serves to optimize speed of generating other sequence values by minimizing the number of disc operations. The initial setting is CACHE and the size is set to 50, even though this value is not officially documented and can later be changed without prior warning. Therefore, it is always better to specify the explicit value.</li>
<li>The SQL Server does not retain the whole range of individual values in its memory. It only retains two numbers: the current value and the number of free values remaining in the cache. Later, we will see how exactly cache works.</li>
</ul>
<h3>2. Basic Sequence</h3>
<p>Little is needed for creating a simple sequence: run the following command: CREATE SEQUENCE with at least the basic setting:</p>
<pre class="lang:tsql decode:true">CREATE SEQUENCE dbo.MySequence
	AS INT
    START WITH 1
    INCREMENT BY 1 ;
GO</pre>
<p>Our new sequence is the closest to that, which we know as IDENTITY(1,1). The start value is 1 and the increment is also 1. We only determined the data type, INT, because the initial data type, BIGINT, is unnecessarily too large for most scenarios. Therefore, our sequence corresponds with the following use of IDENTITY when defining the columns: ID INT NOT NULL IDENTITY(1,1).</p>
<p>We can view the sequences in Management Studio and if necessary, modify its settings:</p>
<p><img fetchpriority="high" decoding="async" class="alignnone size-full wp-image-1809" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Management-Studio-Tree.png" alt="Sequences-Management-Studio-Tree" width="236" height="417" /></p>
<p>After right clicking on Properties, details about the sequence, including the possibility to restart it, will appear:</p>
<p><img decoding="async" class="alignnone size-full wp-image-1812" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Management-Studio-Properties.png" alt="Sequences-Management-Studio-Properties" width="744" height="677" /></p>
<p>The same as other objects, sequences also have their own management view (DMV), where we can find their list and configuration details:</p>
<pre class="lang:tsql decode:true">SELECT * FROM sys.sequences
</pre>
<p>The only thing which we are not able to find out from sys.sequences, are the current values of the CACHE setting. It is possible to find these out using the following system tables but only when we connect to the instance as an administrator using a Dedicated Administrator Connection (DAC):</p>
<pre class="lang:tsql decode:true">SELECT * FROM sys.sysschobjs WHERE id = OBJECT_ID('dbo.MySequence')
SELECT * FROM sys.sysobjvalues WHERE objid = OBJECT_ID('dbo.MySequence')</pre>
<p><img decoding="async" class="alignnone size-full wp-image-1813" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-System-Tables.png" alt="Sequences-System-Tables" width="792" height="100" /></p>
<p>To find out how exactly to read the displayed information and to find out more about the internal cache management of sequences, click <a href="http://sqlhints.com/2013/08/19/sequence-cache-management-sql-server-2012">here</a>.</p>
<h3>3. Generating New Values</h3>
<p>If we already have a sequence created, it is time to show you how to call it and how to obtain new values for further use.</p>
<p>There are two possibilities of generating new values:</p>
<ol style="list-style-type: lower-alpha;">
<li>If we want to obtain a single value (SELECT NEXT VALUE)</li>
<li>If we want to obtain values in a specific range (sys.sp_sequence_get_range)</li>
</ol>
<p><strong>SELECT NEXT VALUE FOR &lt;sequence&gt;</strong></p>
<p>Using this clause, we will obtain a new value for every calling from the sequence:</p>
<pre class="lang:tsql decode:true">SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1815" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-NEXT-VALUE-FOR.png" alt="Sequences-NEXT-VALUE-FOR" width="122" height="221" /></p>
<p>We see that for every calling SELECT NEXT VALUE FOR we obtained another value from our sequence.</p>
<p><strong>sys.sp_sequence_get_range</strong></p>
<p>With the aid of the <a href="https://msdn.microsoft.com/en-us/library/ff878352.aspx">sys.sp_sequence_get_range</a> system procedure, we can ask for more values at once, which can for example be very useful for applications, which process a large amount of data and simultaneously run the insertion of new rows into the database in more threads. Each thread can for example request a calling of a procedure by another 50 sequence values and the range which it obtains does not overlap with ranges, which were generated for other threads.</p>
<pre class="lang:tsql decode:true ">DECLARE
	@FirstSeqNum SQL_VARIANT, @LastSeqNum SQL_VARIANT, @CycleCount INT,
	@SeqIncr SQL_VARIANT, @SeqMinVal SQL_VARIANT, @SeqMaxVal sql_variant

EXEC sys.sp_sequence_get_range
	@sequence_name = N'dbo.MySequence',
	@range_size = 10,
	@range_first_value = @FirstSeqNum OUTPUT,
	@range_last_value = @LastSeqNum OUTPUT,
	@range_cycle_count = @CycleCount OUTPUT,
	@sequence_increment = @SeqIncr OUTPUT,
	@sequence_min_value = @SeqMinVal OUTPUT,
	@sequence_max_value = @SeqMaxVal OUTPUT

SELECT
	@FirstSeqNum AS FirstVal, @LastSeqNum AS LastVal, @CycleCount AS CycleCount,
	@SeqIncr AS SeqIncrement, @SeqMinVal AS MinSeq, @SeqMaxVal AS MaxSeq
GO 3</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1816" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Get-Range.png" alt="Sequences-Get-Range" width="448" height="129" /></p>
<p>Using the GO 3 trick, we called the procedure a total of three times and from the results we can see that we don’t obtain a list of generated values, therefore, 3 * 10 rows but only 3 * one row, which tells us the first and last value of our range (FirstVal, LastVal) and the increment (SeqIncrement), which is sufficient for us to be able to finish calculating the individual values. CycleCount together with MinSeq and MaxSeq provides us with valuable information in case the obtained range appears on the edge, when the sequence automatically restarts from the beginning.</p>
<h3>4. Cyclical Sequences</h3>
<p>With the CYCLE parameter, we can determine that following the exhaustion of its range, the sequence automatically restarts from the minimum value, which is either the lowest value of the data type or a value determined using the MINVALUE configuration.</p>
<p>The following script illustrates a simple example of cyclical behavior:</p>
<pre class="lang:tsql decode:true">CREATE SEQUENCE dbo.MySequence
 AS INT
 START WITH 1
 INCREMENT BY 1
 MINVALUE 1
 MAXVALUE 3
 CYCLE
GO

SELECT NEXT VALUE FOR dbo.[MySequence] SeqValue, name
FROM [sys].[sysobjects]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1821" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Cycle.png" alt="Sequences-Cycle" width="293" height="191" /></p>
<p>We created a dbo.MySequence sequence and we set a MINVALUE = 1 and MAXVALUE = 3 and ran it with CYCLE. In the test inquiry, we see that the sequence is continuously repeating and therefore, we can for example use it as a similar function <a href="https://msdn.microsoft.com/en-us/library/ms175126.aspx">NTILE()</a>.</p>
<p>It is important to not forget to state the MINVALUE setting because otherwise the sequence will restart from the minimum value of the data type:</p>
<pre class="lang:tsql mark:5 decode:true">CREATE SEQUENCE dbo.[MySequence] 
	AS INT
	START WITH 1
	INCREMENT BY 1
	-- MINVALUE 1
	MAXVALUE 3
	CYCLE
GO

SELECT NEXT VALUE FOR dbo.[MySequence] SeqValue, name
FROM [sys].[sysobjects]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1823" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Cycle-No-MinValue.png" alt="Sequences-Cycle-No-MinValue" width="356" height="134" /></p>
<h3>5. Restart Sequence</h3>
<p>Apart from the sequence’s automatic restart using CYCLE, we can restart the sequence from the beginning with the following command:</p>
<pre class="lang:tsql decode:true">ALTER SEQUENCE dbo.MySequence RESTART WITH 1 
GO</pre>
<p>If we assume WITH 1, the sequence will restart from the value determined upon its creation.</p>
<h3>6. OVER()</h3>
<p>The OVER() clause enables us to determine the order in which the sequence values will be generated in relation to the individual rows of the data set.</p>
<pre class="lang:tsql decode:true ">CREATE SEQUENCE dbo.MySequence 
    START WITH 1
    INCREMENT BY 1
GO

SELECT NEXT VALUE FOR dbo.MySequence OVER(ORDER BY Name), name
FROM [sys].[sysobjects]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1825" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-OVER.png" alt="Sequences-OVER" width="300" height="134" /></p>
<p>The clause can seem useless but only until we encounter one of the unpleasant limitations of sequences: we cannot use them in queries together with TOP, ORDER and OFFSET, as is illustrated in this example:</p>
<pre class="lang:tsql mark:3 decode:true">SELECT NEXT VALUE FOR dbo.MySequence SeqValue, name
FROM sys.sysobjects
ORDER BY name
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1826" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-ORDER-Error.png" alt="Sequences-ORDER-Error" width="927" height="29" /></p>
<h3>7. Transactions</h3>
<p>The same as for IDENTITY, sequences are also generated out of the context of the transaction and ROLLBACK leads to loss of the generated values:</p>
<pre class="lang:tsql decode:true ">SELECT NEXT VALUE FOR dbo.MySequence SeqValue
GO

BEGIN TRAN

	SELECT NEXT VALUE FOR dbo.MySequence SeqValue

ROLLBACK
GO

SELECT NEXT VALUE FOR dbo.MySequence SeqValue
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1828" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Transactions.png" alt="Sequences-Transactions" width="96" height="129" /></p>
<h3>8. Sequence as DEFAULT Value of a column</h3>
<p>The NEXT VALUE FOR clause can be used when creating a table as a DEFAULT value of the column, which presents the answer to the question – whether it is possible to replace the traditional use of IDENTITY as a primary table key, with the aid of a sequence. We are simultaneously able to reach a behavior which is not feasible using IDENTITY:</p>
<pre class="lang:tsql mark:2,7 decode:true">CREATE TABLE dbo.TableA 
(	ID INT DEFAULT NEXT VALUE FOR dbo.MySequence PRIMARY KEY,
	Value NVARCHAR(20)
);

CREATE TABLE dbo.TableB
(	ID INT DEFAULT NEXT VALUE FOR dbo.MySequence PRIMARY KEY,
	Value NVARCHAR(20)
);

INSERT INTO dbo.TableA ( [Value] )
	VALUES ('A'), ('B')

INSERT INTO dbo.TableB ( [Value] )
	VALUES ('C'), ('D')

INSERT INTO dbo.TableA ( [Value] )
	VALUES ('E'), ('F')
GO

SELECT * FROM dbo.TableA
SELECT * FROM dbo.TableB
GO

SELECT * FROM dbo.TableA
UNION ALL
SELECT * FROM dbo.TableB
ORDER BY ID
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1832" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Using-As-DEFAULT.png" alt="Sequences-Using-As-DEFAULT" width="100" height="298" /></p>
<p>The highlighted rows in the script indicate that we used our dbo.MySequence sequence as an initial value for the ID column. We used the sequence simultaneously in two tables, which enables us to have two non-overlapping values when inserting data into both tables. Without sequences with similar behavior, it has to either be implemented with the aid of a complicated logic or by a third table, which has an IDENTITY column and is a source of new values.</p>
<h3>9. INSERT</h3>
<p>We can use the sequences directly in the INSERT command for inserting new values:</p>
<pre class="lang:tsql decode:true ">CREATE TABLE dbo.TableA 
(	ID INT PRIMARY KEY,
	Value NVARCHAR(20)
);

INSERT INTO dbo.TableA ( [ID], [Value] )
	VALUES	(NEXT VALUE FOR dbo.MySequence, 'A'),
			(NEXT VALUE FOR dbo.MySequence, 'B')

GO

INSERT INTO dbo.TableA ( [ID], [Value] )
	SELECT NEXT VALUE FOR dbo.MySequence, 'C'
GO

SELECT * FROM dbo.TableA
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1835" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Using-In-INSERT.png" alt="Sequences-Using-In-INSERT" width="100" height="77" /></p>
<h3>10. Limitations</h3>
<p>For using sequences, a number of limitations exist. Even though the majority of them can be avoided by another syntax record or the query logic, they are not always pleasant and it is necessary to keep them in mind.</p>
<p><strong>Sequences cannot be used:</strong></p>
<ul>
<li>in view, functions and calculated columns</li>
<li>as a parameter table-valued function</li>
<li>as an argument of aggregate functions (SUM(), …)</li>
<li>in conditional expressions when using CASE, CHOOSE, COALESCE, IIF, ISNULL, or NULLIF</li>
<li>in FETCH, OVER, OUTPUT, ON, PIVOT, UNPIVOT, GROUP BY, HAVING, COMPUTE, COMPUTE BY, or FOR XML clauses</li>
<li>if the database is in the read-only mode</li>
<li>in subqueries including common table expressions and derived tables</li>
<li>in the MERGE command (except if it is inserted into tables using MERGE, where the sequence is used as a DEFAULT)</li>
<li>as a check or as a rule</li>
<li>as a default in the user table type</li>
<li>in row-constructor (VALUES), if it is not directly a part of INSERT</li>
<li>in the WHERE clause</li>
<li>together with TOP, OFFSET, ORDER clauses</li>
</ul>
<p><strong>Examples:</strong></p>
<p><strong>UNION (ALL)</strong></p>
<pre class="lang:tsql decode:true">SELECT NEXT VALUE FOR dbo.MySequence, * FROM sys.[columns]
UNION ALL
SELECT NEXT VALUE FOR dbo.MySequence, * FROM sys.[columns]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1837" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-UNION-Error.png" alt="Sequences-UNION-Error" width="927" height="29" /></p>
<p>We can avoid an Error using this alternative syntax.</p>
<pre class="lang:tsql decode:true">SELECT NEXT VALUE FOR dbo.MySequence SEQ, *
FROM (
	SELECT * FROM sys.[columns]
	UNION ALL
	SELECT * FROM sys.[columns]
	) a
GO</pre>
<p><strong>ISNULL()</strong></p>
<pre class="lang:tsql decode:true ">DECLARE @i INT
SELECT ISNULL(@i,(NEXT VALUE FOR dbo.MySequence))
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1838" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-ISNULL-Error.png" alt="Sequences-ISNULL-Error" width="655" height="29" /></p>
<p>Alternative syntax:</p>
<pre class="lang:tsql decode:true ">DECLARE @i INT
DECLARE @SEQ INT

SET @SEQ = NEXT VALUE FOR dbo.[MySequence]

SELECT ISNULL(@i, @SEQ)
GO</pre>
<h3>11. Bugs</h3>
<p>The <a href="https://support.microsoft.com/en-us/kb/3011465">KB3011465</a> error is known and worth mentioning. This is where the generation of duplicate sequence values can occur in the SQL Server 2012 and 2014 versions. This can occur if instance is currently working under memory pressure.</p>
<h3>12. Links</h3>
<ul>
<li><a href="https://msdn.microsoft.com/en-us/library/ff878091.aspx">MSDN</a></li>
<li><a href="https://www.simple-talk.com/sql/learn-sql-server/sql-server-sequence-basics/">SQL Server SEQUENCE Basics &#8211; Simple Talk</a></li>
<li><a href="http://sqlhints.com/2013/04/14/sequence-in-sql-server-2012/">SEQUENCE IN SQL SERVER 2012 (SqlHints.com)</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sqlpowered.com/sequences-introduction/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Sekvence</title>
		<link>https://sqlpowered.com/sekvence/</link>
					<comments>https://sqlpowered.com/sekvence/#respond</comments>
		
		<dc:creator><![CDATA[Jan Dvořák]]></dc:creator>
		<pubDate>Mon, 02 May 2016 20:23:23 +0000</pubDate>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[sequences]]></category>
		<guid isPermaLink="false">https://sqlpowered.com/?p=1470</guid>

					<description><![CDATA[Sekvence přicházejí jako novinka s SQL Serverem 2012 a přinášejí konečně ANSI standard pro generování číselných sekvencí, který v SQL Serveru dosud chyběl a ani IDENTITY či jiná různá řešení na míru ho nemohla plně nahradit. Sekvence jsou samostatné objekty, které můžeme vytvářet na úrovni databázových schémat, a nejsou přiřazeny...]]></description>
										<content:encoded><![CDATA[<p>Sekvence přicházejí jako novinka s SQL Serverem 2012 a přinášejí konečně ANSI standard pro generování číselných sekvencí, který v SQL Serveru dosud chyběl a ani IDENTITY či jiná různá řešení na míru ho nemohla plně nahradit. Sekvence jsou samostatné objekty, které můžeme vytvářet na úrovni databázových schémat, a nejsou přiřazeny ani tabulce ani sloupci jako tomu dosud bylo u IDENTITY. Jejich hlavním účelem je generovat číselné hodnoty ve vzestupném nebo sestupném pořadí a v intervalech definovaných při jejich vytvoření. Pro vygenerování nových hodnot jsou sekvence referencovány přímo aplikačním nebo databázovým kódem. V článku si velmi podrobně ukážeme, jak sekvence vytvářet, jaká mají nastavení, jak získávat nové hodnoty a také se z pohledu databázového vývojáře zamyslíme na tím, zda je lze považovat za plnohodnotnou náhradu IDENTITY a co by v tomto případě znamenalo nahradit v existující databázi IDENTITY sekvencemi.<span id="more-1470"></span></p>
<h3>1. Vytváření sekvencí</h3>
<p>Sekvence se vytvářejí podobně jako jiné databázové objekty pomocí příkazu CREATE SEQUENCE a odstraňují se příkazem DROP SEQUENCE. Stejně je tomu i jejich změnou, která se provádí pomocí ALTER SEQUENCE.</p>
<p>Syntaxe příkazu CREATE SEQUENCE je následující:</p>
<pre class="lang:tsql highlight:0 decode:true">CREATE SEQUENCE [schema_name . ] sequence_name
    [ AS [ built_in_integer_type | user-defined_integer_type ] ]
    [ START WITH &lt;constant&gt; ]
    [ INCREMENT BY &lt;constant&gt; ]
    [ { MINVALUE [ &lt;constant&gt; ] } | { NO MINVALUE } ]
    [ { MAXVALUE [ &lt;constant&gt; ] } | { NO MAXVALUE } ]
    [ CYCLE | { NO CYCLE } ]
    [ { CACHE [ &lt;constant&gt; ] } | { NO CACHE } ]
    [ ; ]</pre>
<p><strong>[schema_name].[sequence_name]</strong></p>
<ul>
<li>Pro název sekvencí platí stejná pravidla jako pro jiné databázové objekty. Sekvence patři vždy pouze jednomu databázovému schématu a v rámci schématu musí být její název unikátní. Protože se jedná o samostatné databázové objekty, můžeme pro ně aplikovat nastavení bezpečnosti na rovni schématu na rozdíl o IDENTITY, kde žádné explicitní přiřazení práv možné nebylo.</li>
</ul>
<p><strong>AS [ built_in_integer_type | user-defined_integer_type ]</strong></p>
<ul>
<li>Každá sekvence má svůj systémový nebo uživatelský datový typ a může se jednat pouze o některý z těchto číselných datových typů:
<ul>
<li><strong>tinyint</strong> &#8211; od 0 do 255</li>
<li><strong>smallint</strong> &#8211; od -32,768 do 32,767</li>
<li><strong>int</strong> &#8211; od -2,147,483,648  do 2,147,483,647</li>
<li><strong>bigint</strong> &#8211; od -9,223,372,036,854,775,808 do 9,223,372,036,854,775,807</li>
<li><strong>decimal</strong> a <strong>numeric</strong>, ale pouze s nulovým počtem desetinných míst</li>
<li>uživatelské datové typy založené na výše uvedených systémových typech</li>
</ul>
</li>
<li>Výchozím datovým typem je bigint a je dobré na to při vytváření sekvencí pamatovat, protože pro většinu případů nebude rozsah tohoto datového typu potřeba a je vhodnější zvolit co nejmenší možný datový typ.</li>
</ul>
<p><strong>START WITH &lt;constant&gt;</strong></p>
<ul>
<li>Určuje první hodnotu, kterou bude sekvence vracet. Je to nesmírně důležité nastavení, protože bez jejího použití bude první vrácenou hodnotou minimální nebo maximální hodnota použitého datového typu, a to podle toho, zda jde o sekvenci vzestupnou nebo sestupnou. Hodnota musí být samozřejmě v rozsahu zvoleného datového typu.</li>
</ul>
<p><strong>INCREMENT BY &lt;constant&gt;</strong></p>
<ul>
<li>Hodnota určující velikost ikrementu nebo dekrementu při každém volání funkce NEXT VALUE FOR, která získává se sekvence další hodnotu. Hodnota nemůže být 0 a výchozí nastavení je 1. Hodnota může být pochopitelně i záporná, podobně jako u IDENTITY.</li>
</ul>
<p><strong>MINVALUE &lt;constant&gt; | NO MINVALUE</strong></p>
<ul>
<li>Určuje minimální hodnotu, která bude vygenerována danou sekvencí. Pokud není určena, je minimální hodnotou vždy nejnižší hodnota použitého datového typu, případně 0 pro tinyint.</li>
</ul>
<p><strong>MAXVALUE &lt;constant&gt; | NO MAXVALUE</strong></p>
<ul>
<li>Určuje horní hranici sekvence. Není-li nastavena, je horní hranicí maximální hodnota datového typu.</li>
</ul>
<p><strong>CYCLE | NO CYCLE</strong></p>
<ul>
<li>Tato vlastnost určuje, zda se po dosažení maximální hodnoty pro vzestupné sekvence či minimální hodnoty pro sestupné sekvence má začít sekvence opět generovat od začátku. Výchozí nastavení je NO CYCLE a při dosažení hraniční maximální hodnoty je vygenerována výjimka. Nesmíme zapomenout na to, že pokud dojde k obnově cyklu, je sekvence restartována od minimální nebo maximální hodnoty, nikoliv od START WITH hodnoty.</li>
</ul>
<p><strong>CACHE [&lt;constant&gt; ] | NO CACHE</strong></p>
<ul>
<li>Slouží k optimalizaci rychlosti generování dalších hodnot sekvence tím, že minimalizuje počet diskových operací. Výchozí nastavení je CACHE a velikost je nastavena na 50, i když tato hodnota není oficiálně zdokumentována a může být později změněna bez předchozího upozornění. Je tedy vždy lepší specifikovat explicitní hodnotu.</li>
<li>SQL Serve si nedrží v paměti celý rozsah jednotlivých hodnot, ale pouze dvě čísla: aktuální hodnotu a počet zbývající volných hodnot v cache. Jak přesně cachování pracuje si ukážeme dále.</li>
</ul>
<h3>2. Základní sekvence</h3>
<p>K vytvoření jednoduché sekvence nám stačí opravdu málo: spustit příkaz CREATE SEQUENCE s minimem základní nastavení:</p>
<pre class="lang:tsql decode:true">CREATE SEQUENCE dbo.MySequence
	AS INT
    START WITH 1
    INCREMENT BY 1 ;
GO</pre>
<p>Naše nová sekvence je nejblíže tomu, co známe jako IDENTITY(1,1). Startovní hodnota je 1 a inkrement také 1. Pouze jsme určili datový typ INT, protože výchozí datový type BIGINT je pro většinu scénářů zbytečně velký. Naše sekvence tedy odpovídá následujícímu použití IDENTITY při definici sloupce: ID INT NOT NULL IDENTITY(1,1).</p>
<p>Sekvenci si můžeme prohlédnout pomocí Management Studia a upravit případně její nastavení:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1809" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Management-Studio-Tree.png" alt="Sequences-Management-Studio-Tree" width="236" height="417" /></p>
<p>Po kliknutí pravým tlačítkem -&gt; Properties se zobrazí podrobnosti o sekvenci včetně možnosti provést její restart:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1812" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Management-Studio-Properties.png" alt="Sequences-Management-Studio-Properties" width="744" height="677" /></p>
<p>Podobně jako jiné objekty mají i sekvence své vlastní management view (DMV), kde najdeme jejich seznam a podrobnosti konfigurace:</p>
<pre class="lang:tsql decode:true">SELECT * FROM sys.sequences
</pre>
<p>Jedinou věc, kterou nedokážeme ze sys.sequences zjistit jsou aktuální hodnoty nastavení CACHE. Ty je možné zjistit z následujících systémových tabulek, ale pouze tehdy, pokud se k instanci připojíme jako administrátoři pomocí dedikovaného připojení (DAC):</p>
<pre class="lang:tsql decode:true">SELECT * FROM sys.sysschobjs WHERE id = OBJECT_ID('dbo.MySequence')
SELECT * FROM sys.sysobjvalues WHERE objid = OBJECT_ID('dbo.MySequence')</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1813" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-System-Tables.png" alt="Sequences-System-Tables" width="792" height="100" /></p>
<p>Jak přesně zobrazené informace číst a více o interním cache managementu sekvencí najdete <a href="http://sqlhints.com/2013/08/19/sequence-cache-management-sql-server-2012">zde</a>.</p>
<h3>3. Generování nových hodnot</h3>
<p>Pokud již máme vytvořenou sekvenci, je čas si ukázat, jak ji budeme volat a získávat nové hodnoty pro další použití.</p>
<p>Existují dvě možnosti, jak můžeme generovat nového hodnoty</p>
<p>a) chceme získávat jedinou hodnotu (SELECT NEXT VALUE)</p>
<p>b) chceme získat hodnoty v určitém rozsahu (sys.sp_sequence_get_range)</p>
<p><strong>SELECT NEXT VALUE FOR &lt;sequence&gt;</strong></p>
<p>Pomocí této klauzule získáme ze sekvence novou hodnotu a to pro každé volání:</p>
<pre class="lang:tsql decode:true">SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
SELECT NEXT VALUE FOR dbo.MySequence AS NewSeqValue
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1815" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-NEXT-VALUE-FOR.png" alt="Sequences-NEXT-VALUE-FOR" width="122" height="221" /></p>
<p>Vidíme, že pro každé volání SELECT NEXT VALUE FOR jsme získali z naší sekvence další hodnotu.</p>
<p><strong>sys.sp_sequence_get_range</strong></p>
<p>Pomocí systémové procedury <a href="https://msdn.microsoft.com/en-us/library/ff878352.aspx">sys.sp_sequence_get_range</a> můžeme požádat o více hodnot zároveň, což může být velmi užitečné např. pro aplikace, které zpracovávají ve více vláknech velké množství dat a provádí souběžně vkládání nových řádků do databáze. Každé vlákno si může požádat voláním procedury např. o dalších 50 hodnot sekvence a rozsah, který obdrží, se nekryje s rozsahy, které byly vygenerovány pro ostatní vlákna.</p>
<pre class="lang:tsql decode:true ">DECLARE
	@FirstSeqNum SQL_VARIANT, @LastSeqNum SQL_VARIANT, @CycleCount INT,
	@SeqIncr SQL_VARIANT, @SeqMinVal SQL_VARIANT, @SeqMaxVal sql_variant

EXEC sys.sp_sequence_get_range
	@sequence_name = N'dbo.MySequence',
	@range_size = 10,
	@range_first_value = @FirstSeqNum OUTPUT,
	@range_last_value = @LastSeqNum OUTPUT,
	@range_cycle_count = @CycleCount OUTPUT,
	@sequence_increment = @SeqIncr OUTPUT,
	@sequence_min_value = @SeqMinVal OUTPUT,
	@sequence_max_value = @SeqMaxVal OUTPUT

SELECT
	@FirstSeqNum AS FirstVal, @LastSeqNum AS LastVal, @CycleCount AS CycleCount,
	@SeqIncr AS SeqIncrement, @SeqMinVal AS MinSeq, @SeqMaxVal AS MaxSeq
GO 3</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1816" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Get-Range.png" alt="Sequences-Get-Range" width="448" height="129" /></p>
<p>Pomocí GO 3 jsme zavolali proceduru celkem třikrát a z výsledků vidíme, že nedostáváme seznam vygenerovaných hodnot, tedy 3 * 10 řádků, ale pouze 3 * jeden řádek, který nám říká, jaké je první a poslední hodnota našeho rozsahu (FirstVal, LastVal) a jaký je inkrement (SeqIncrement), což nám stačí k tomu, abychom si dokázali jednotlivé hodnoty dopočítat. CycleCount spolu s MinSeq a MaxSeq nám poskytují cenné informace pro případ, že získaný rozsah se vyskytuje na hranici, kdy se sekvence automaticky restartuje od začátku.</p>
<h3>4. Cyklické sekvence</h3>
<p>Pomocí CYCLE můžeme určit, že sekvence se po vyčerpání svého rozsahu automaticky restartuje od minimální hodnoty, kterou je buď nejmenší hodnota datového typu nebo hodnota určená pomocí MINVALUE konfigurace.</p>
<p>Jednoduchý příklad cyklického chování si ukážeme v následujícím skriptu:</p>
<pre class="lang:tsql decode:true">CREATE SEQUENCE dbo.MySequence
 AS INT
 START WITH 1
 INCREMENT BY 1
 MINVALUE 1
 MAXVALUE 3
 CYCLE
GO

SELECT NEXT VALUE FOR dbo.[MySequence] SeqValue, name
FROM [sys].[sysobjects]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1821" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Cycle.png" alt="Sequences-Cycle" width="293" height="191" /></p>
<p>Vytvořili jsme sekvenci dbo.MySequence a nastavili jí MINVALUE = 1 a MAXVALUE = 3 a zapnuli CYCLE. V testovacím dotazu vidíme, že sekvence se stále opakuje a může ji tak použít např. jako obdobu funkce <a href="https://msdn.microsoft.com/en-us/library/ms175126.aspx">NTILE()</a>.</p>
<p>Důležité je nezapomenout uvést MINVALUE nastavení, protože jinak se sekvence restartuje od minimálního hodnoty datového typu:</p>
<pre class="lang:tsql mark:5 decode:true">CREATE SEQUENCE dbo.[MySequence] 
	AS INT
	START WITH 1
	INCREMENT BY 1
	-- MINVALUE 1
	MAXVALUE 3
	CYCLE
GO

SELECT NEXT VALUE FOR dbo.[MySequence] SeqValue, name
FROM [sys].[sysobjects]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1823" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Cycle-No-MinValue.png" alt="Sequences-Cycle-No-MinValue" width="356" height="134" /></p>
<h3>5. Restart sekvence</h3>
<p>Kromě automatického restartování sekvence pomocí CYCLE můžeme sekvence restartovat od začátku pomocí následujícího příkazu:</p>
<pre class="lang:tsql decode:true ">ALTER SEQUENCE dbo.MySequence RESTART WITH 1 
GO</pre>
<p>Pokud vynecháme WITH 1, restartuje se sekvence od hodnoty určené při jejím vytvoření.</p>
<h3>6. OVER()</h3>
<p>Klauze OVER() nám umožňuje určit v rámci dotazu pořadí, v jakém budou hodnoty sekvence generovány vůči jednotlivým řádkům datového setu.</p>
<pre class="lang:tsql decode:true ">CREATE SEQUENCE dbo.MySequence 
    START WITH 1
    INCREMENT BY 1
GO

SELECT NEXT VALUE FOR dbo.MySequence OVER(ORDER BY Name), name
FROM [sys].[sysobjects]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1825" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-OVER.png" alt="Sequences-OVER" width="300" height="134" /></p>
<p>Klauzule se může zdát zbytečná, ale jen to té chvíle, než narazíme na jedno z nepříjemných omezení sekvencí: Nelze je použít v dotazu společně s TOP, ORDER a OFFSET, jak ukazuje tento příklad:</p>
<pre class="lang:tsql mark:3 decode:true ">SELECT NEXT VALUE FOR dbo.[MySequence] SeqValue, name
FROM [sys].[sysobjects]
ORDER BY name
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1826" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-ORDER-Error.png" alt="Sequences-ORDER-Error" width="927" height="29" /></p>
<h3>7. Transakce</h3>
<p>Stejně jako IDENTITY i sekvence jsou generovány mimo kontext transakce a ROLLBACK vede ke ztrátě vygenerované hodnoty:</p>
<pre class="lang:tsql decode:true ">SELECT NEXT VALUE FOR dbo.MySequence SeqValue
GO

BEGIN TRAN

	SELECT NEXT VALUE FOR dbo.MySequence SeqValue

ROLLBACK
GO

SELECT NEXT VALUE FOR dbo.MySequence SeqValue
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1828" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Transactions.png" alt="Sequences-Transactions" width="96" height="129" /></p>
<h3>8. Sekvence jako DEFAULT hodnota sloupce</h3>
<p>Klauzuli NEXT VALUE FOR můžeme použít při vytváření tabulky jako DEFAULT hodnotu sloupce, což představuje odpověď na otázku, zda lze pomocí sekvencí nahradit klasické použití IDENTITY jako primárního klíče tabulky. Zároveň jsme schopni dosáhnout chování, které je pomocí IDENTITY nerealizovatelné:</p>
<pre class="lang:tsql mark:2,7 decode:true">CREATE TABLE dbo.TableA 
(	ID INT DEFAULT NEXT VALUE FOR dbo.MySequence PRIMARY KEY,
	Value NVARCHAR(20)
);

CREATE TABLE dbo.TableB
(	ID INT DEFAULT NEXT VALUE FOR dbo.MySequence PRIMARY KEY,
	Value NVARCHAR(20)
);

INSERT INTO [dbo].[TableA] ( [Value] )
	VALUES ('A'), ('B')

INSERT INTO [dbo].[TableB] ( [Value] )
	VALUES ('C'), ('D')

INSERT INTO [dbo].[TableA] ( [Value] )
	VALUES ('E'), ('F')
GO

SELECT * FROM dbo.[TableA]
SELECT * FROM dbo.[TableB]
GO

SELECT * FROM dbo.[TableA]
UNION ALL
SELECT * FROM dbo.[TableB]
ORDER BY ID
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1832" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Using-As-DEFAULT.png" alt="Sequences-Using-As-DEFAULT" width="100" height="298" /></p>
<p>Zvýrazněné řádky ve skriptu ukazují, že jsme naši sekvenci dbo.MySequence použili jako výchozí hodnotu pro sloupec ID. Sekvenci jsme použili zároveň ve dvou tabulkách, což nám umožňuje při vkládání dat do obou tabulek mít ID hodnoty, které se nebudou překrývat. Bez sekvencí se podobné chování musí implementovat buď pomocí složité logiky nebo nebo třetí tabulky, která má sloupec IDENTITY a je zdrojem nových hodnot.</p>
<h3>9. INSERT</h3>
<p>Sekvence můžeme použít přímo v INSERT příkazu pro vkládání nových hodnot:</p>
<pre class="lang:tsql decode:true ">CREATE TABLE dbo.TableA 
(	ID INT PRIMARY KEY,
	Value NVARCHAR(20)
);

INSERT INTO dbo.TableA ( [ID], [Value] )
	VALUES	(NEXT VALUE FOR dbo.MySequence, 'A'),
			(NEXT VALUE FOR dbo.MySequence, 'B')

GO

INSERT INTO dbo.TableA ( [ID], [Value] )
	SELECT NEXT VALUE FOR dbo.MySequence, 'C'
GO

SELECT * FROM dbo.TableA
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1835" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-Using-In-INSERT.png" alt="Sequences-Using-In-INSERT" width="100" height="77" /></p>
<h3>10. Omezení</h3>
<p>Pro použití sekvencí existuje řada omezení, a i když lze většinu z nich obejít jiným syntaktickým zápisem nebo logikou dotazu, nejsou vždy příjemná a je třeba na ně myslet.</p>
<p>Sekvence nelze použít:</p>
<ul>
<li>v pohledech, funkcích a vypočítaných sloupcích</li>
<li>jako parametr table-valued funkce</li>
<li>jako argument agregačních funkcí (SUM(), &#8230;)</li>
<li>ve podmínkových výrazech s použitím CASE, CHOOSE, COALESCE, IIF, ISNULL, or NULLIF</li>
<li>v klauzulích FETCH, OVER, OUTPUT, ON, PIVOT, UNPIVOT, GROUP BY, HAVING, COMPUTE, COMPUTE BY, or FOR XML</li>
<li>pokud je databáze v read-only režimu</li>
<li>ve vnořených dotazech včetně common table expressions a odvozených tabulek</li>
<li>v MERGE příkazu (kromě toho, je-li pomocí MERGE vkládáno do tabulky, kde je sekvence použita jako DEFAULT)</li>
<li>jako check omezení nebo rule</li>
<li>jako default v uživatelském tabulkovém typu</li>
<li>v row-konstruktoru (VALUES), pokud není přímo součástí INSERTu</li>
<li>ve WHERE klauzuli</li>
<li>společně s TOP, OFFSET, ORDER klauzulemi</li>
</ul>
<p>Příklady:</p>
<p><strong>UNION (ALL)</strong></p>
<pre class="lang:tsql decode:true ">SELECT NEXT VALUE FOR dbo.MySequence, * FROM sys.[columns]
UNION ALL
SELECT NEXT VALUE FOR dbo.MySequence, * FROM sys.[columns]
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1837" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-UNION-Error.png" alt="Sequences-UNION-Error" width="927" height="29" /></p>
<p>Error obejdeme pomocí tohoto alternativního zápisu:</p>
<pre class="lang:tsql decode:true ">SELECT NEXT VALUE FOR dbo.MySequence SEQ, *
FROM (
	SELECT * FROM sys.[columns]
	UNION ALL
	SELECT * FROM sys.[columns]
	) a
GO</pre>
<p><strong>ISNULL()</strong></p>
<pre class="lang:tsql decode:true ">DECLARE @i INT
SELECT ISNULL(@i,(NEXT VALUE FOR dbo.MySequence))
GO</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1838" src="https://sqlpowered.com/wp-content/uploads/2016/05/Sequences-ISNULL-Error.png" alt="Sequences-ISNULL-Error" width="655" height="29" /></p>
<p>Alternativní zápis:</p>
<pre class="lang:tsql decode:true ">DECLARE @i INT
DECLARE @SEQ INT

SET @SEQ = NEXT VALUE FOR dbo.[MySequence]

SELECT ISNULL(@i, @SEQ)
GO</pre>
<h3>11. Chyby a KB</h3>
<p>Ze známých chyb stojí za zmínku <a href="https://support.microsoft.com/en-us/kb/3011465">KB3011465</a>, kdy ve verzích SQL Server 2012 a 2014 může dojít k vygenerování duplicitních hodnot sekvencí, pokud je instance aktuálně pracuje pod nedostatkem paměti</p>
<h3>12. Odkazy</h3>
<ul>
<li><a href="https://msdn.microsoft.com/en-us/library/ff878091.aspx">MSDN</a></li>
<li><a href="https://www.simple-talk.com/sql/learn-sql-server/sql-server-sequence-basics/">SQL Server SEQUENCE Basics &#8211; Simple Talk</a></li>
<li><a href="http://sqlhints.com/2013/04/14/sequence-in-sql-server-2012/">SEQUENCE IN SQL SERVER 2012 (SqlHints.com)</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sqlpowered.com/sekvence/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
