এসকিউএল এনভিচারার এবং ভোচারআর সীমাবদ্ধতা


100

সব মিলিয়ে আমার কাছে একটি বৃহত (অনিবার্য) ডায়নামিক এসকিউএল কোয়েরি রয়েছে। নির্বাচনের মানদণ্ডে ক্ষেত্রের সংখ্যার কারণে গতিশীল এসকিউএলযুক্ত স্ট্রিং 4000 অক্ষরেরও বেশি বৃদ্ধি পাচ্ছে। এখন, আমি বুঝতে পারি যে এখানে 4000 সর্বাধিক সেট রয়েছে NVARCHAR(MAX), তবে বিবৃতিটির জন্য সার্ভার প্রোফাইলারে এক্সিকিউটড এসকিউএলটির দিকে তাকান

DELARE @SQL NVARCHAR(MAX);
SET @SQL = 'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO

(!?) কাজ করার মতো মনে হচ্ছে, এটির চেয়েও বড় অন্য একটি ক্যোয়ারির জন্য এটি একটি ত্রুটি ছুঁড়ে যা এই 4000 সীমা (!?) এর সাথে সম্পর্কিত এটি মূলত এই 4000 সীমাটির পরে সমস্ত এসকিউএলকে ছাঁটাই করে এবং আমাকে একটি বাক্য গঠন ত্রুটিতে ফেলে দেয়। এটি প্রোফাইলে থাকা সত্ত্বেও, এটি পুরো (!?) এ এই গতিশীল এসকিউএল কোয়েরিটি দেখাচ্ছে ।

এখানে ঠিক কী ঘটছে এবং আমি কি এই @ এসকিউএল ভেরিয়েবলটিকে ভর্চারে রূপান্তর করে এটিকে চালিয়ে ফেলা উচিত?

আপনার সময় জন্য ধন্যবাদ।

পুনশ্চ. এই বড় কোয়েরিগুলি দেখার জন্য 4000 টিরও বেশি অক্ষর মুদ্রণ করতে সক্ষম হতে পেরে ভাল লাগবে। নিম্নলিখিত 4000 এর মধ্যে সীমাবদ্ধ

SELECT CONVERT(XML, @SQL);
PRINT(@SQL);

অন্য কোন দুর্দান্ত উপায় আছে?


4
ম্যাক্স 4000 সীমাটির সমার্থক শব্দ নয়, এর 1..4000 বা MAX
অ্যালেক্স কে।

আপনি কেন সি # ডিএল এবং সেটিংয়ের সাথে প্রশ্নটি ট্যাগ করেছেন কেন এটি কেবল একটি
এসকিএল

সম্পাদিত। স্পট করার জন্য ধন্যবাদ ...
চাঁদরাত্রি

PRINT 4000 টি অক্ষর (ইউনিকোডের জন্য) বা 8000 অক্ষরে (একক বাইট এনকোডিংয়ের জন্য) সংমিশ্রণ করবে। আমি সন্দেহ করি এটাই এখানে বিভ্রান্তির উত্স।
redcalx

উত্তর:


235

আমি বুঝতে পারি যে এখানে 4000 সর্বাধিক সেট রয়েছে NVARCHAR(MAX)

আপনার বোঝাপড়া ভুল। nvarchar(max)2 গিগাবাইট ডেটা (1 বিলিয়ন ডাবল বাইট অক্ষর) পর্যন্ত সঞ্চয় করতে পারে।

অনলাইনে বইগুলিতে এনসিআর এবং এনভারচর থেকে ব্যাকরণটি হয়

nvarchar [ ( n | max ) ]

|চরিত্র মানে এই বিকল্প। যেমন আপনি উভয় n বা আক্ষরিক নির্দিষ্ট max

আপনি যদি কোনও নির্দিষ্ট উল্লেখ করতে চান nতবে এটি অবশ্যই 1 এবং 4,000 এর মধ্যে হওয়া উচিত তবে maxএটি একটি বৃহত অবজেক্ট ডেটাটাইপ হিসাবে সংজ্ঞায়িত করে (প্রতিস্থাপন ntextযার জন্য অবমূল্যায়ন করা হয়)।

আসলে এসকিউএল সার্ভার ২০০৮ এ দেখে মনে হচ্ছে যে একটি ভেরিয়েবলের জন্য 2 গিগাবাইটের সীমাটি পর্যাপ্ত জায়গার অধীনে অনির্দিষ্টকালের জন্য অতিক্রম করা যেতে পারে tempdb( এখানে দেখানো হয়েছে )

আপনার প্রশ্নের অন্যান্য অংশ সম্পর্কিত

সংক্ষিপ্তকরণ যখন ডেটাটাইপ উপর নির্ভর করে কাটা।

  1. varchar(n) + varchar(n) 8,000 অক্ষর ছাঁটাই করা হবে।
  2. nvarchar(n) + nvarchar(n) 4,000 অক্ষর ছাঁটাই করা হবে।
  3. varchar(n) + nvarchar(n)4,000 অক্ষর ছাঁটাই করা হবে। nvarcharফলাফল বেশি তাই উচ্চতর প্রাধান্য রয়েছেnvarchar(4,000)
  4. [n]varchar(max)+ [n]varchar(max)কেটে যাবে না (<2GB এর জন্য)।
  5. varchar(max)+ varchar(n)কে <কা> ছাড়বে না (<2 গিগাবাইটের জন্য) এবং ফলাফলটি টাইপ করা হবে varchar(max)
  6. varchar(max)+ nvarchar(n)কে <কা> ছাড়বে না (<2 গিগাবাইটের জন্য) এবং ফলাফলটি টাইপ করা হবে nvarchar(max)
  7. nvarchar(max)+ varchar(n)প্রথমে varchar(n)ইনপুটটি রূপান্তর করবে nvarchar(n)এবং তারপরে সংক্ষেপণ করবে। স্ট্রিংয়ের দৈর্ঘ্য যদি varchar(n)4,000 টিরও বেশি অক্ষরের চেয়ে বেশি হয় তবে nvarchar(4000)নিক্ষেপটি হবে এবং ছাঁটাই হবে

স্ট্রিং লিটারেলের ডেটাটাইপস

আপনি যদি Nউপসর্গটি ব্যবহার করেন এবং স্ট্রিংটি <= 4,000 অক্ষর দীর্ঘ হয় তবে টাইপ করা হবে স্ট্রিংটির দৈর্ঘ্য nvarchar(n)কোথায় n। তাই N'Foo'বলে গণ্য হবে nvarchar(3)উদাহরণস্বরূপ। যদি স্ট্রিং 4,000 টির চেয়ে বেশি অক্ষরের হয় তবে এটি হিসাবে বিবেচিত হবেnvarchar(max)

আপনি যদি Nউপসর্গটি ব্যবহার না করেন এবং স্ট্রিংটি <= 8,000 অক্ষর দীর্ঘ হয় তবে এটি টাইপ করা হবে কারণ স্ট্রিংটির দৈর্ঘ্য varchar(n)কোথায় n। আর যদি হয়varchar(max)

উপরের উভয়ের জন্য যদি স্ট্রিংয়ের দৈর্ঘ্য শূন্য হয় তবে n1 তে সেট করা আছে।

আরও নতুন সিনট্যাক্স উপাদান।

1.CONCAT ফাংশন এখানে সাহায্য না

DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);

SELECT DATALENGTH(@A5000 + @A5000), 
       DATALENGTH(CONCAT(@A5000,@A5000));

উভয় উপসংহারের জন্য উপরেরটি 8000 প্রদান করে।

2. সাবধান+=

DECLARE @A VARCHAR(MAX) = '';

SET @A+= REPLICATE('A',5000) + REPLICATE('A',5000)

DECLARE @B VARCHAR(MAX) = '';

SET @B = @B + REPLICATE('A',5000) + REPLICATE('A',5000)


SELECT DATALENGTH(@A), 
       DATALENGTH(@B);`

ফিরে আসে

-------------------- --------------------
8000                 10000

দ্রষ্টব্য যে @Aকাটা কাটা সম্মুখীন।

আপনি যে সমস্যার মুখোমুখি হচ্ছেন তা কীভাবে সমাধান করবেন।

আপনি দু'জন নন maxডেটাটাইপ একসাথে তৈরি করার কারণে বা আপনি কোনও টাইপযুক্ত স্ট্রিংয়ের (এমনকি ) varchar(4001 - 8000)স্ট্রিংটিতে সংযোগ দিচ্ছেন বলে আপনি ছাঁটাই পেয়ে যাচ্ছেন ।nvarcharnvarchar(max)

দ্বিতীয় সমস্যাটি এড়ানোর জন্য কেবল নিশ্চিত হয়ে নিন যে সমস্ত স্ট্রিং লিটারালগুলি (বা কমপক্ষে 4001 - 8000 রেঞ্জের দৈর্ঘ্য সহ) প্রবর্তিত আছে N

প্রথম সমস্যাটি এড়াতে এসাইনমেন্টটি থেকে পরিবর্তন করুন

DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;

প্রতি

DECLARE @SQL NVARCHAR(MAX) = ''; 
SET @SQL = @SQL + N'Foo' + N'Bar'

যাতে কোনও NVARCHAR(MAX)শুরু থেকে এই সম্মেলনে জড়িত থাকে (প্রতিটি যুক্তির ফলাফল হিসাবে এটিও NVARCHAR(MAX)প্রচার করবে)

দেখার সময় কাটা কাটা এড়ানো

আপনার "গ্রিড টু ফলাফল" মোডটি নির্বাচিত হয়েছে তা আপনি ব্যবহার করতে পারেন তা নিশ্চিত করুন

select @SQL as [processing-instruction(x)] FOR XML PATH 

এসএসএমএস বিকল্পগুলি আপনাকে XMLফলাফলের জন্য সীমাহীন দৈর্ঘ্য সেট করতে দেয় । processing-instructionবিট যেমন অক্ষর সমস্যা এড়াতে <যেমন দেখানো &lt;


4
@ কিলারক্যাম - আপনি সম্ভবত nvarchar(4000)এই পথে একটি নিখরচায় কাস্ট পেয়ে যাচ্ছেন। যদি একটি স্ট্রিং আক্ষরিক 4,000 বর্ণের কম হয় তবে এটি হিসাবে বিবেচিত হবে nvarchar(x)। এটির প্রতি সম্মান জানাতে অন্য nvarchar(x)মানটি ছেঁটে ফেলা হবে না বরংnvarchar(max)
মার্টিন স্মিথ

4
@ কিলারক্যাম - আমার প্রথম মন্তব্য অনুসারে আপনি সম্ভবত কেটে যাচ্ছেন। অ্যাসাইনমেন্টটি DECLARE @SQL NVARCHAR(MAX) = ''; SET @SQL = @SQL + এমনভাবে পরিবর্তন করার চেষ্টা করুন যাতে কোনও একটি NVARCHAR(MAX)কনটেনটেশনে জড়িত থাকে।
মার্টিন স্মিথ

4
@ কিলারক্যাম - সম্ভবত আপনার স্ট্রিং 4,000 থেকে 8,000 টির মধ্যে রয়েছে। Nপ্রিফিক্সটি যেটি nvarchar(max)এটিকে ছাড়া বিবেচনা করা হবে এটির সাথে varchar(n)তখনই স্পষ্টভাবে বিবেচনা করা হবে nvarchar(4000)যখন আপনি কোনটির সাথে একমত পোষণ করবেনnvarchar
মার্টিন স্মিথ

4
আমি এই উত্তরটি দ্বারা আলোকিত
মুদাসসির হাসান

4
দুর্দান্ত উত্তর। অনেক ধন্যবাদ!
জন বেল

6

ঠিক আছে, সুতরাং যদি পরে লাইনটি নীচে দেওয়া হয় তবে আপনার কাছে এমন একটি ক্যোয়ারী রয়েছে যা অনুমোদিত মাপের চেয়ে বড় (এটি বাড়তে থাকলে এমনও হতে পারে) আপনাকে এটিকে খণ্ডগুলিতে ভেঙে স্ট্রিংয়ের মানগুলি প্রয়োগ করতে হবে। সুতরাং, আসুন আমরা নীচের মত একটি সঞ্চিত পদ্ধতি আছে:

CREATE PROCEDURE ExecuteMyHugeQuery
    @SQL VARCHAR(MAX) -- 2GB size limit as stated by Martin Smith
AS
BEGIN
    -- Now, if the length is greater than some arbitrary value
    -- Let's say 2000 for this example
    -- Let's chunk it
    -- Let's also assume we won't allow anything larger than 8000 total
    DECLARE @len INT
    SELECT @len = LEN(@SQL)

    IF (@len > 8000)
    BEGIN
        RAISERROR ('The query cannot be larger than 8000 characters total.',
                   16,
                   1);
    END

    -- Let's declare our possible chunks
    DECLARE @Chunk1 VARCHAR(2000),
            @Chunk2 VARCHAR(2000),
            @Chunk3 VARCHAR(2000),
            @Chunk4 VARCHAR(2000)

    SELECT @Chunk1 = '',
           @Chunk2 = '',
           @Chunk3 = '',
           @Chunk4 = ''

    IF (@len > 2000)
    BEGIN
        -- Let's set the right chunks
        -- We already know we need two chunks so let's set the first
        SELECT @Chunk1 = SUBSTRING(@SQL, 1, 2000)

        -- Let's see if we need three chunks
        IF (@len > 4000)
        BEGIN
            SELECT @Chunk2 = SUBSTRING(@SQL, 2001, 2000)

            -- Let's see if we need four chunks
            IF (@len > 6000)
            BEGIN
                SELECT @Chunk3 = SUBSTRING(@SQL, 4001, 2000)
                SELECT @Chunk4 = SUBSTRING(@SQL, 6001, (@len - 6001))
            END
              ELSE
            BEGIN
                SELECT @Chunk3 = SUBSTRING(@SQL, 4001, (@len - 4001))
            END
        END
          ELSE
        BEGIN
            SELECT @Chunk2 = SUBSTRING(@SQL, 2001, (@len - 2001))
        END
    END

    -- Alright, now that we've broken it down, let's execute it
    EXEC (@Chunk1 + @Chunk2 + @Chunk3 + @Chunk4)
END

2

আপনি খুব nvarchar পাঠ্য ব্যবহার। এর অর্থ আপনার বিশাল স্ট্রিংয়ের আগে আপনার কেবল "এন" থাকতে হয়েছিল এবং এটিই! আর সীমাবদ্ধতা নেই

DELARE @SQL NVARCHAR(MAX);
SET @SQL = N'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO

4
এটি পুরো চিত্র নয় ... আপনি যদি এন উপসর্গ ব্যবহার করেন এবং স্ট্রিং <= 4,000 অক্ষর দীর্ঘ হয় তবে টাইপ করা হবে nvarchar(n)যেখানে স্ট্রিংটির দৈর্ঘ্য n n সুতরাং উদাহরণস্বরূপ N'Foo 'হিসাবে বিবেচিত হবে nvarchar(3)। যদি স্ট্রিং 4,000 টির চেয়ে বেশি অক্ষরের হয় তবে এটি হিসাবে বিবেচিত হবে nvarchar(max)। আপনি যদি এন উপসর্গ ব্যবহার না করেন এবং স্ট্রিং <= 8,000 অক্ষর দীর্ঘ হয় তবে এটি টাইপ করা হবে varchar(n)যেখানে n স্ট্রিংয়ের দৈর্ঘ্য। আর যদি হয় varchar(max)। উপরের উভয়ের জন্য যদি স্ট্রিংয়ের দৈর্ঘ্য শূন্য হয় তবে n কে 1 এ সেট করা হয়েছে
মুনকনাইট

1

গৃহীত উত্তরটি আমাকে সহায়তা করেছে তবে মামলার বিবৃতি জড়িত ভার্চারগুলিকে সংক্ষেপণ করতে গিয়ে আমি বিভক্ত হয়ে পড়েছিলাম। আমি জানি ওপি-র প্রশ্নে মামলার বিবৃতি জড়িত নয় তবে আমি ভেবেছিলাম যে আমার মতো অন্যদের জন্য এখানে পোস্ট করা সহায়ক হবে যারা কেস স্টেটমেন্ট জড়িত দীর্ঘ গতিশীল এসকিউএল বিবৃতি তৈরির সংগ্রাম করতে গিয়ে এখানে শেষ হয়েছিল।

স্ট্রিং কনটেন্টেশন সহ কেস স্টেটমেন্টগুলি ব্যবহার করার সময় স্বীকৃত উত্তরে বর্ণিত বিধিগুলি কেস স্টেটমেন্টের প্রতিটি বিভাগে স্বাধীনভাবে প্রয়োগ হয়।

declare @l_sql varchar(max) = ''

set @l_sql = @l_sql +
case when 1=1 then
    --without this correction the result is truncated
    --CONVERT(VARCHAR(MAX), '')
 +REPLICATE('1', 8000)
 +REPLICATE('1', 8000)
end

print len(@l_sql)

0
declare @p varbinary(max)
set @p = 0x
declare @local table (col text)

SELECT   @p = @p + 0x3B + CONVERT(varbinary(100), Email)
 FROM tbCarsList
 where email <> ''
 group by email
 order by email

 set @p = substring(@p, 2, 100000)

 insert @local values(cast(@p as varchar(max)))
 select DATALENGTH(col) as collen, col from @local

result collen > 8000, length col value is more than 8000 chars
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.