How to Store a String Var Greater Than Varchar(Max)

How to store a string var greater than varchar(max)?

Seriously - VARCHAR(MAX) can store up to 2 GB of data - not just 8000 characters.....

Try this:

DECLARE @myVar VARCHAR(MAX) = ''

DECLARE @ix INT = 1

WHILE @ix < 1000
BEGIN
set @myVar = @myVar + CAST('bla bla bla' AS VARCHAR(MAX))
SET @ix = @ix + 1
END

SELECT DATALENGTH(@myvar)

This will return a value higher than 8000 characters after 1000 iterations.

The point is: if you're using varchar(max), you need to make sure to always cast all your strings to varchar(max) explicitly - as I did in this example. Otherwise, SQL Server will fall back to "regular" varchar processing, and that's indeed limited to 8000 characters....

Is Varchar(Max) take much space than Varchar(N) if text length is fixed?

Varchar(MAX) & Varchar(n) reserve fix space for same text store in Column.
I have two table tblMaxData & tblNData and both table have single column with VARCGAR(MAX) & VARCHAR(N). Column have 'Hello' Value in Both Table. After then i was checked space , both column has same occupied Space.
Sample Image

Sample Image

How does SQL Server store more than 4000 characters in NVARCHAR(max)?

Yes it is possible - according to the MSDN documentation:

nvarchar [ ( n | max ) ]

Variable-length Unicode string data. n defines the string length and can be a value from 1 through 4,000. max indicates that the maximum storage size is 2^31-1 bytes (2 GB). The storage size, in bytes, is two times the actual length of data entered + 2 bytes. The ISO synonyms for nvarchar are national char varying and national character varying.

So if you specify nvarchar(max) you can store up to 1 billion 2-byte Unicode characters. That's Leo Tolstoj's War and Peace well over a hundred times over ....

SQL Server stores those max columns into special structures internally, which makes it possible to get around the 8K limit of the SQL Server pages. It works - but it's more effort than just storing a few hundred bytes on a page, so this storage system does pose more strain on SQL Server - use it with care, use it only when you really need to (and most definitely don't just make all your columns (n)varchar(max), just because you're lazy!)

Check out this really good article on Simple Talk: What's the Point of Using VARCHAR(n) Anymore? - it explains very nicely how (max) datatypes are different and less suited for smaller strings - use only when really needed!

why varchar(max) is not storing data more than 8000 charaters

You are truncating the data to 8000 bytes before inserting it. To create a value longer than 8000 characters you must use varchar(max) data type, whereas the type of 'a' is just varchar.

create table test(name varchar(max))
insert into test
values(replicate(CAST('a' AS varchar(MAX)), 100000));

select len(name) from test;

How to run a more than 8000 characters SQL statement from a variable?

If you are on SQL Server 2008 or newer you can use VARCHAR(MAX)

DECLARE @sql VARCHAR(MAX)

sql varchar(max) vs varchar(fix)

MSDN

  • Use varchar when the sizes of the column data entries vary
    considerably.
  • Use varchar(max) when the sizes of the column data entries vary
    considerably, and the size might exceed 8,000 bytes.

When the the length is specified in declaring a VARCHAR variable or column, the maximum length allowed is 8000. If the length is greater than 8000, you have to use the MAX specifier as the length. If a length greater than 8000 is specified, the following error will be encountered (assuming that the length specified is 10000):

The size (10000) given to the type 'varchar' exceeds the maximum allowed for any data type (8000).

UPDATE :-
I found a link which I would like to share:-

Here

There is not much performance difference between Varchar[(n)] and Varchar(Max). Varchar[(n)] provides better performance results compared to Varchar(Max). If we know that data to be stored in the column or variable is less than or equal to 8000 characters, then using this Varchar[(n)] data type provides better performance compared to Varchar(Max).Example: When I ran the below script by changing the variable @FirstName type to Varchar(Max) then for 1 million assignments it is consistently taking double time than when we used data type as Varchar(50) for variable @FirstName.

DECLARE @FirstName VARCHAR(50), @COUNT INT=0, @StartTime DATETIME = GETDATE()
WHILE(@COUNT < 1000000)
BEGIN
SELECT @FirstName = 'Suraj', @COUNT = @COUNT +1
END
SELECT DATEDIFF(ms,@StartTime,GETDATE()) 'Time Taken in ms'
GO

Can i store more than 8000 character in a field of SQL table?

Kind of yes, but this gets messy rapidly, and in fact the work around would be worse performance than the varchar(max) option. The issue is the limit of 8060 bytes is permitted on-page for a single row. You can exceed that limit but as long as you accept the data being stored off-page and on a page elsewhere.

Preferred Option : use Varchar(Max) and allow LOB storage to be used.

Alternative : Use multiple varchar(8000) fields, and split / concatenate your string - the data will get Short Large Object'ed (SLOB) and the varchar(8000) fields will be stored off in different pages. This will make it less performant - not to mention the split / concatenate performance issues.

2nd Alternative - compress the data, but there is no guarentee you can still store it within the 8k limit.

Deprecated : Text - do not use this as a solution

In short - do not try to avoid varchar(max) - you would make your life a lot worse.

Maximum size of a varchar(max) variable

As far as I can tell there is no upper limit in 2008.

In SQL Server 2005 the code in your question fails on the assignment to the @GGMMsg variable with

Attempting to grow LOB beyond maximum allowed size of 2,147,483,647
bytes.

the code below fails with

REPLICATE: The length of the result exceeds the length limit (2GB) of
the target large type.

However it appears these limitations have quietly been lifted. On 2008

DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681); 

SET @y = REPLICATE(@y,92681);

SELECT LEN(@y)

Returns

8589767761

I ran this on my 32 bit desktop machine so this 8GB string is way in excess of addressable memory

Running

select internal_objects_alloc_page_count
from sys.dm_db_task_space_usage
WHERE session_id = @@spid

Returned

internal_objects_alloc_page_co 
------------------------------
2144456

so I presume this all just gets stored in LOB pages in tempdb with no validation on length. The page count growth was all associated with the SET @y = REPLICATE(@y,92681); statement. The initial variable assignment to @y and the LEN calculation did not increase this.

The reason for mentioning this is because the page count is hugely more than I was expecting. Assuming an 8KB page then this works out at 16.36 GB which is obviously more or less double what would seem to be necessary. I speculate that this is likely due to the inefficiency of the string concatenation operation needing to copy the entire huge string and append a chunk on to the end rather than being able to add to the end of the existing string. Unfortunately at the moment the .WRITE method isn't supported for varchar(max) variables.

Paul White confirms the above supposition here and also provides the information that the variable is held entirely in memory if <= 512KB and changes to the tempdb-based backup scheme for values larger than that.

Addition

I've also tested the behaviour with concatenating nvarchar(max) + nvarchar(max) and nvarchar(max) + varchar(max). Both of these allow the 2GB limit to be exceeded. Trying to then store the results of this in a table then fails however with the error message Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes. again. The script for that is below (may take a long time to run).

DECLARE @y1 VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),2147483647); 
SET @y1 = @y1 + @y1;
SELECT LEN(@y1), DATALENGTH(@y1) /*4294967294, 4294967292*/

DECLARE @y2 NVARCHAR(MAX) = REPLICATE(CAST('X' AS NVARCHAR(MAX)),1073741823);
SET @y2 = @y2 + @y2;
SELECT LEN(@y2), DATALENGTH(@y2) /*2147483646, 4294967292*/

DECLARE @y3 NVARCHAR(MAX) = @y2 + @y1
SELECT LEN(@y3), DATALENGTH(@y3) /*6442450940, 12884901880*/

/*This attempt fails*/
SELECT @y1 y1, @y2 y2, @y3 y3
INTO Test


Related Topics



Leave a reply



Submit