Sql server e>

Sql server e>,sql-server,tsql,sql-server-2008,varchar,varcharmax,Sql Server,Tsql,Sql Server 2008,Varchar,Varcharmax,更正 该表可以按varchar(最大值)显示,但您指定的值仅为nvarchar(4000) 就是 maxcolumn = maxvalues + smallstring1 + **unicodestring** + smallstring3 + smallstring4 ... 由于nvarchar>varchar,右侧将保持在nvarchar(4000)最大值。当指定给max列时,它将截断 您必须确保varchar的所有值都位于右侧 它仍然像整数除法。。。让我困惑的是当varchar是800

更正

该表可以按varchar(最大值)显示,但您指定的值仅为nvarchar(4000)

就是

maxcolumn = maxvalues + smallstring1 + **unicodestring** + smallstring3 + smallstring4 ...
由于nvarchar>varchar,右侧将保持在nvarchar(4000)最大值。当指定给max列时,它将截断

您必须确保varchar的所有值都位于右侧

它仍然像整数除法。。。让我困惑的是当varchar是8000时的4000限制。。。这意味着某个地方的nvarchar


我怀疑问题在于字符串和转换操作。尝试将您的转换更改为VARCHAR(max)或将整个表达式转换为VARCHAR(max)。

问题不在于我的列数据类型或长度,而在于调用我的.NET
SendMail
过程,该过程只接受NVARCHAR(4000)作为BODY参数。。。.NET
SqlString
类型的明显翻译

因此,现在我开始研究如何将更长的字符串传递给CLR汇编函数。

这一问题及其解决方案在上面的文章中有很好的解释,解决方案是在串联中添加一个VARCHAR(MAX)

声明@SQL VARCHAR(最大值) 设置@SQL=''
SET@SQL=@SQL+'xxxxxx(n)

好的,在MERGE语句中,它设置DST.BODY=DST.BODY+。既然DST.BODY位于右侧,并且定义为VARCHAR(MAX),那么这不符合要求吗?@eidylon:那么INSERT…呢?@gbn-SRC.BODY应该将整个表达式提升到MAX,如果我正确阅读MSDN的话。我的更新现在执行DST.BODY=DST.BODY+CONVERT(VARCHAR(MAX),)并且INSERT同样插入CONVERT(VARCHAR(MAX),)到DST.BODY,但仍在截断。“如果字符串串联的结果超过8000字节的限制,则结果将被截断。但是,如果至少有一个串联的字符串是大值类型,则不会发生截断。”好的,我尝试将分配/连接到DST.BODY的整个表达式包装为CONVERT(VARCHAR(max)),但它仍在默默地截断超过4000的任何内容。请查看我的更新。。。您的右侧有一个nvarchar,它正在从varchar(max)隐式转换为nvarchar(4000)。根据我的更新,您可以将整个RHS表达式包装为CONVERT(varchar(max)吗?我看到的唯一没有显式转换为varchar(max)的是文本字符串,如“”。文字是否作为NVARCHAR输入?SRC。都转换为VARCHAR,CHAR函数会将CHAR type.FYI返回给任何感兴趣的。。。将NVARCHAR(MAX)字段传递到CLR存储过程是通过使用属性修饰特定参数来完成的,这样您就不知道表中的数据是否正常了?你从没想过要在这件事上做LEN?所以这个问题是错误的和误导性的……我显然错误地认为,这一定是T-SQL代码的问题。我没有想过看.NET代码,因为当涉及到.NET时,我习惯于只处理字符串,而不关心长度。我没有做过太多的.NET/CLR-SQL集成,所以我不想去那里看看。我们都曾有过这样的日子,因为它盯着我们的脸,我们错过了显而易见的事情,我们需要一双新的眼睛来帮助我们指出正确的方向。谁会相信呢!多么奇怪的行为!谢谢你澄清这一点。
ALTER PROCEDURE [system].[SendAccumulatedEmails]
AS 
BEGIN
    SET NOCOUNT ON;

    DECLARE @SENTS  BIGINT = 0;

    DECLARE @ROWS TABLE (
        ROWID    ROWID, 
        DATED    DATETIME, 
        ADDRESS  NAME, 
        SUBJECT  VARCHAR(1000), 
        BODY     VARCHAR(MAX)
    )
    INSERT INTO @ROWS SELECT ROWID, DATED, ADDRESS, SUBJECT, BODY 
    FROM system.EMAILQUEUE 
        WHERE ACCUMULATE = 1 AND SENT IS NULL
        ORDER BY ADDRESS, DATED

    DECLARE @EMAILS TABLE (
        ADDRESS  NAME, 
        ALLIDS   VARCHAR(1000),
        BODY     VARCHAR(MAX) 
    )

    DECLARE @PRVRID ROWID = NULL, @CURRID ROWID = NULL
    SELECT @CURRID = MIN(ROWID) FROM @ROWS
    WHILE @CURRID IS NOT NULL BEGIN
        MERGE @EMAILS AS DST 
        USING (SELECT * FROM @ROWS WHERE ROWID = @CURRID) AS SRC 
        ON SRC.ADDRESS = DST.ADDRESS 
        WHEN MATCHED THEN 
            UPDATE SET 
                DST.ALLIDS = DST.ALLIDS + ', ' + CONVERT(VARCHAR,ROWID), 
                DST.BODY = DST.BODY + '<i>'+CONVERT(VARCHAR,SRC.DATED,101)+' '
                            +CONVERT(VARCHAR,SRC.DATED,8)
                            +':</i> <b>'+SRC.SUBJECT+'</b>'+CHAR(13)+SRC.BODY
                            +' (Message ID '+CONVERT(VARCHAR,SRC.ROWID)+')'
                            +CHAR(13)+CHAR(13)
        WHEN NOT MATCHED BY TARGET THEN 
            INSERT (ADDRESS, ALLIDS, BODY) VALUES (
                SRC.ADDRESS, 
                CONVERT(VARCHAR,ROWID), 
                '<i>'+CONVERT(VARCHAR,SRC.DATED,101)+' '
                    +CONVERT(VARCHAR,SRC.DATED,8)+':</i> <b>'
                    +SRC.SUBJECT+'</b>'+CHAR(13)+SRC.BODY
                    +' (Message ID '+CONVERT(VARCHAR,SRC.ROWID)+')'
                    +CHAR(13)+CHAR(13));

        SELECT @PRVRID = @CURRID, @CURRID = NULL
        SELECT @CURRID = MIN(ROWID) FROM @ROWS WHERE ROWID > @PRVRID
    END 

    DECLARE @MAILFROM VARCHAR(100) = system.getOption('MAILFROM'), 
    DECLARE @SMTPHST VARCHAR(100) = system.getOption('SMTPSERVER'), 
    DECLARE @SMTPUSR VARCHAR(100) = system.getOption('SMTPUSER'), 
    DECLARE @SMTPPWD VARCHAR(100) = system.getOption('SMTPPASS')

    DECLARE @ADDRESS NAME, @BODY VARCHAR(MAX), @ADDL VARCHAR(MAX)
    DECLARE @SUBJECT VARCHAR(1000) = 'Accumulated Emails from LIJSL'

    DECLARE @PRVID NAME = NULL, @CURID NAME = NULL 
    SELECT @CURID = MIN(ADDRESS) FROM @EMAILS
    WHILE @CURID IS NOT NULL BEGIN
        SELECT @ADDRESS = ADDRESS, @BODY = BODY 
        FROM @EMAILS WHERE ADDRESS = @CURID

        SELECT @BODY = @BODY + 'This is an automated message sent from an unmonitored mailbox.'+CHAR(13)+'Do not reply to this message; your message will not be read.'
        SELECT @BODY = 
            '<style type="text/css">
                * {font-family: Tahoma, Arial, Verdana;}
                p {margin-top: 10px; padding-top: 10px; border-top: single 1px dimgray;} 
                p:first-child {margin-top: 10px; padding-top: 0px; border-top: none 0px transparent;}
            </style>' 
            + @BODY 

        exec system.LogIt @SUBJECT, @BODY

        BEGIN TRY 
            exec system.SendMail @SMTPHST, @SMTPUSR, @SMTPPWD, @MAILFROM, 
                             @ADDRESS, NULL, NULL, @SUBJECT, @BODY, 1
        END TRY 
        BEGIN CATCH
            DECLARE @EMSG NVARCHAR(2048) = 'system.EMAILQUEUE.AI:'+ERROR_MESSAGE()
            SELECT @ADDL = 'TO:'+@ADDRESS+CHAR(13)+'SUBJECT:'+@SUBJECT+CHAR(13)+'BODY:'+@BODY
            exec system.LogIt @EMSG,@ADDL
        END CATCH

        SELECT @PRVID = @CURID, @CURID = NULL
        SELECT @CURID = MIN(ADDRESS) FROM @EMAILS WHERE ADDRESS > @PRVID
    END

    UPDATE system.EMAILQUEUE SET SENT = getdate()
    FROM system.EMAILQUEUE E, @ROWS R WHERE E.ROWID = R.ROWID
END
maxcolumn = maxvalues + smallstring1 + **unicodestring** + smallstring3 + smallstring4 ...