简体   繁体   English

对于Nvarchar(Max),我只在TSQL中获得4000个字符?

[英]For Nvarchar(Max) I am only getting 4000 characters in TSQL?

This is for SS 2005. 这是SS 2005。

Why I am i only getting 4000 characters and not 8000? 为什么我只有4000个字符而不是8000个?

It truncates the string @SQL1 at 4000. 它在4000处截断字符串@ SQL1。

ALTER PROCEDURE sp_AlloctionReport(
    @where NVARCHAR(1000),
    @alldate NVARCHAR(200),
    @alldateprevweek NVARCHAR(200))
AS
    DECLARE @SQL1 NVARCHAR(Max)

    SET @SQL1 = 'SELECT DISTINCT VenueInfo.VenueID, VenueInfo.VenueName, VenuePanels.PanelID, 
    VenueInfo.CompanyName, VenuePanels.ProductCode, VenuePanels.MF, VenueInfo.Address1, 
    VenueInfo.Address2, '' As AllocationDate, '' As AbbreviationCode, VenueInfo.Suburb, VenueInfo.Route, VenueInfo.ContactFirstName, 
    VenueInfo.ContactLastName, VenueInfo.SuitableTime, VenueInfo.OldVenueName, 
    VenueCategories.Category, VenueInfo.Phone, VenuePanels.Location, VenuePanels.Comment, 
    [VenueCategories].[Category] + '' Allocations'' AS ReportHeader, 
    ljs.AbbreviationCode AS PrevWeekCampaign
    FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID = VenuePanels.VenueID) 
    INNER JOIN VenueCategories ON VenueInfo.CategoryID = VenueCategories.CategoryID) 
    LEFT JOIN (SELECT CampaignProductions.AbbreviationCode, VenuePanels.PanelID, CampaignAllocations.AllocationDate
                    FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID=VenuePanels.VenueID) INNER JOIN CampaignAllocations ON VenuePanels.PanelID=CampaignAllocations.PanelID) INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID=CampaignProductions.CampaignID) INNER JOIN VenueCategories ON VenueInfo.CategoryID=VenueCategories.CategoryID
                    WHERE ' + @alldateprevweek + ') ljs
                ON VenuePanels.PanelID = ljs.PanelID) 
    INNER JOIN (SELECT VenueInfo.VenueID, VenuePanels.PanelID, VenueInfo.VenueName, VenueInfo.CompanyName, VenuePanels.ProductCode, 
                VenuePanels.MF, VenueInfo.Address1, VenueInfo.Address2, CampaignAllocations.AllocationDate, 
                CampaignProductions.AbbreviationCode, VenueInfo.Suburb, VenueInfo.Route, VenueInfo.ContactFirstName, 
                VenueInfo.ContactLastName, VenueInfo.SuitableTime, VenueInfo.OldVenueName, VenueCategories.Category, 
                VenueInfo.Phone, VenuePanels.Location, VenuePanels.Comment, [Category] + '' Allocations'' AS ReportHeader, 
                ljs2.AbbreviationCode AS PrevWeekCampaign
                FROM ((((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID = VenuePanels.VenueID) 
                INNER JOIN CampaignAllocations ON VenuePanels.PanelID = CampaignAllocations.PanelID) 
                INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID = CampaignProductions.CampaignID) 
                INNER JOIN VenueCategories ON VenueInfo.CategoryID = VenueCategories.CategoryID) 
                LEFT JOIN (SELECT CampaignProductions.AbbreviationCode, VenuePanels.PanelID, CampaignAllocations.AllocationDate
                                FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID=VenuePanels.VenueID) INNER JOIN CampaignAllocations ON VenuePanels.PanelID=CampaignAllocations.PanelID) INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID=CampaignProductions.CampaignID) INNER JOIN VenueCategories ON VenueInfo.CategoryID=VenueCategories.CategoryID
                                WHERE ' + @alldateprevweek + ') ljs2
                            ON VenuePanels.PanelID = ljs2.PanelID
                WHERE ' + @alldate + ' AND ' + @where + ') ljs3
                ON VenueInfo.VenueID = ljs3.VenueID
    WHERE (((VenuePanels.PanelID)<>ljs3.[PanelID] And 
        (VenuePanels.PanelID) Not In (SELECT PanelID FROM CampaignAllocations WHERE ' + @alldateprevweek + ')) 
        AND ' + @where + ')
    UNION ALL
     SELECT VenueInfo.VenueID, VenueInfo.VenueName, VenuePanels.PanelID, VenueInfo.CompanyName, VenuePanels.ProductCode, 
    VenuePanels.MF, VenueInfo.Address1, VenueInfo.Address2, CampaignAllocations.AllocationDate, 
    CampaignProductions.AbbreviationCode, VenueInfo.Suburb, VenueInfo.Route, VenueInfo.ContactFirstName, 
    VenueInfo.ContactLastName, VenueInfo.SuitableTime, VenueInfo.OldVenueName, VenueCategories.Category, 
    VenueInfo.Phone, VenuePanels.Location, VenuePanels.Comment, [Category] + '' Allocations'' AS ReportHeader, 
    ljs.AbbreviationCode AS PrevWeekCampaign
    FROM ((((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID = VenuePanels.VenueID) 
    INNER JOIN CampaignAllocations ON VenuePanels.PanelID = CampaignAllocations.PanelID) 
    INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID = CampaignProductions.CampaignID) 
    INNER JOIN VenueCategories ON VenueInfo.CategoryID = VenueCategories.CategoryID) 
    LEFT JOIN (SELECT CampaignProductions.AbbreviationCode, VenuePanels.PanelID, CampaignAllocations.AllocationDate
                    FROM (((VenueInfo INNER JOIN VenuePanels ON VenueInfo.VenueID=VenuePanels.VenueID) INNER JOIN CampaignAllocations ON VenuePanels.PanelID=CampaignAllocations.PanelID) INNER JOIN CampaignProductions ON CampaignAllocations.CampaignID=CampaignProductions.CampaignID) INNER JOIN VenueCategories ON VenueInfo.CategoryID=VenueCategories.CategoryID
                    WHERE ' + @alldateprevweek + ') ljs
                ON VenuePanels.PanelID = ljs.PanelID
    WHERE ' + @alldate + ' AND ' + @where

    Select @SQL1

You have declared this as nvarchar(max) which allows 2GB of data so it will store 2GB. 您已将此声明为nvarchar(max),允许2GB数据,因此它将存储2GB。

What is happening: 怎么了:

  • The datatype is not yet nvarchar(max) until assignment to @sql1 分配给@sql1之前,数据类型还不是nvarchar(max)
  • Before that, it's a collection of strings, each less than 4000 ( constants ) 在此之前,它是一个字符串集合,每个字符串少于4000( 常量
  • You are concatenating short constants with short variables (short = < 4000) 您将短常量与短变量连接(短= <4000)
  • So you have 4000 characters put into @sql1 所以你在@ sql1中放了4000个字符

So, you have make sure you have nvarchar(max) on the right hand side. 因此,您必须确保右侧有nvarchar(max)。

One idea. 一个想法。 The 2nd line concatenates nvarchar(max) with a constant = nvarchar(max) 第二行将nvarchar(max)与constant = nvarchar(max)连接起来

SET @SQL1 = ''
SET @SQL1 = @SQL1 + 'SELECT DISTINCT Venue...
   ....

It's no different to the integer division that happens in every langauge. 它与每个语言中发生的整数除法没有什么不同。

declare @myvar float
set @myvar = 1/2 --gives zero because it's integer on the right

Operator precedence (infers datatype precedence) is always "assignment" last... why should unicode strings in SQL Server be any different? 运算符优先级(推断数据类型优先级)总是“赋值”最后...为什么SQL Server中的unicode字符串会有所不同?

Update : gbn's answer is right, and I was wrong. 更新gbn的答案是正确的,我错了。 As MSDN points out, nvarchar(max) supports up to 2^31-1 bytes of data, stored as UCS-2 (2 bytes per character, plus 2 for BOM). 正如MSDN所指出的那样,nvarchar(max)支持最多2 ^ 31-1个字节的数据,存储为UCS-2(每个字符2个字节,BOM加2个)。 Your problem seems to be with string concatenation, not data type limits. 您的问题似乎是字符串连接,而不是数据类型限制。

That said, if you're using it to build a SQL string, why not use VARCHAR? 也就是说,如果您使用它来构建SQL字符串,为什么不使用VARCHAR? Do you have field names that aren't representable by the database's native character set (usually Latin-1)? 您是否有数据库的本机字符集(通常是Latin-1)无法表示的字段名称?

Finally -- you could simplify your entire problem by just not using dynamic SQL in your stored procedure. 最后 - 您可以通过在存储过程中不使用动态SQL来简化整个问题。 Create some table-valued functions that take your where-clause strings and return tables, and then just JOIN them in your procedure. 创建一些表值函数,这些函数接受where子句字符串并返回表,然后在您的过程中加入它们。 As a bonus it will almost certainly be much faster, since at very least the database will be able to cache the SP body as a prepared statement. 作为奖励,它几乎肯定会更快,因为至少数据库将能够将SP主体缓存为准备好的声明。

i resolve problem just include N character before every string and problem solved for example 我解决问题只是在每个字符串之前包含N个字符并解决问题

declare @sql nvarchar(max) = '' + @Where + 'SomeThing';

must be 一定是

declare @sql nvarchar(max) = N'' + @Where + N'SomeThing';

if you set string to empty also must set N'' 如果你将字符串设置为空也必须设置N''

if @where is null
set @where = N''

:-) simple answer :-)简单的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM