16

2005年春夏用です。

8000 文字ではなく 4000 文字しか表示されないのはなぜですか?

文字列 @SQL1 を 4000 で切り捨てます。

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
4

3 に答える 3

50

これを 2GB のデータを許可する nvarchar(max) として宣言したため、2GB が格納されます。

何が起こっている:

  • @sql1 に割り当てられるまで、データ型はまだ nvarchar(max) ではありません
  • その前は、それぞれが 4000 未満の文字列のコレクションです (定数)
  • 短い定数と短い変数を連結しています (short = < 4000)
  • したがって、@sql1 には 4000 文字が入ります。

したがって、右側に nvarchar(max) があることを確認してください。

1 つのアイデア。2 行目は、nvarchar(max) を定数 = nvarchar(max) と連結します。

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

これは、すべての言語で行われる整数除算と同じです。

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

演算子の優先順位 (データ型の優先順位を推測) は常に「割り当て」が最後です... SQL Server のユニコード文字列が異なるのはなぜですか?

于 2009-09-03T05:42:07.827 に答える
4

更新: gbn の答えは正しく、私は間違っていました。MSDNが指摘しているように、nvarchar(max) は最大 2^31-1 バイトのデータをサポートし、UCS-2 (1 文字あたり 2 バイト、BOM 用に 2 バイト) として保存されます。あなたの問題は、データ型の制限ではなく、文字列の連結にあるようです。

とはいえ、それを使用して SQL 文字列を作成しているのであれば、なぜ VARCHAR を使用しないのでしょうか? データベースのネイティブ文字セット (通常は Latin-1) で表現できないフィールド名はありますか?

最後に、ストアド プロシージャで動的 SQL を使用しないだけで、問題全体を単純化できます。where 句の文字列を受け取ってテーブルを返すいくつかのテーブル値関数を作成し、プロシージャでそれらを JOIN するだけです。おまけとして、少なくともデータベースは SP 本体を準備済みステートメントとしてキャッシュできるため、ほぼ確実にはるかに高速になります。

于 2009-09-03T04:19:46.103 に答える