【问题标题】:is too long. Maximum length is 128. while using double quotes太长。最大长度为 128。使用双引号时
【发布时间】:2018-08-03 09:28:04
【问题描述】:

我在 MSSQL 中有一个 SP,它会将错误日志插入到 SQL 中

ALTER PROCEDURE [dbo].[TestLog]


@PrimaryName nvarchar(255),
@ERROR nvarchar(4000)

AS
BEGIN


insert into Process_Log 
(
PrimaryName ,
ERROR
) VALUES
(
@PrimaryName ,
@ERROR
)

END

我的示例错误消息是这样的:

Violation of PRIMARY KEY constraint 'PK__AP__2EC21549E681BC94'. Cannot insert duplicate key in object 'dbo.Test'. The duplicate key value is (215009).
The statement has been terminated.

因为我在字符串中有 ',所以我必须使用双引号并 SET QUOTED_IDENTIFIER OFF。

我无法更改错误消息或对其进行编辑,因为它来自其他应用程序。

编辑:

我的进程表结构:

CREATE TABLE [dbo].[Process_Log](
    [PrimaryName] [nvarchar](255) NULL,
    [ERROR] [nvarchar](max) NULL
) 

【问题讨论】:

  • 那么这里的问题是什么?您是否知道您也可以将 ' 替换为 '',这与双引号等一样有效?
  • 是的,我知道,但正如我所说,我无法编辑错误消息。它必须保持原样。当我使用 SET QUOTED_IDENTIFIER OFF 并且字符串的 len 超过 128 个 SQL 抛出和错误(len 太长)时。我试图做 left(@ERROR, 128) 但它不适用于双引号中的值。
  • 您的错误消息字段非常适合 varchar(max) - 我经常看到错误日志,其中消息/堆栈跟踪存储为长字段,但最终可能不得不截断关键消息。有些人开了一个 2 小时的会议,讨论如何制作他们的错误表,不知道数据类型 text、varchar(max) 等。
  • 我的表有 nvarchar(MAX) 作为错误字段。
  • 在您的程序中,参数限制为 4000 个字符

标签: sql-server stored-procedures sql-insert


【解决方案1】:

在您的查询中替换:

insert into Process_Log 
(
PrimaryName ,
ERROR
) VALUES
(
@PrimaryName ,
@ERROR
)

与:

insert into Process_Log 
(
PrimaryName ,
ERROR
) VALUES
(
@PrimaryName ,
REPLACE(@ERROR, '''', '''''')
)

这不会更改错误消息,只是“转义”单引号,以免 SQL Server 混淆。

您还需要去掉 QUOTED_IDENTIFIER 位并忘记双引号。


我开始认为这不是 SQL Server,因为您在下面的评论中添加的“东西”肯定不是我所知道的 SQL...如果我尝试它不会做任何事情通过 SSMS 运行它。

试试这个:

DECLARE @test TABLE (error VARCHAR(MAX));
--Doesn't work due to single quotes
--INSERT INTO @test SELECT 'Violation of PRIMARY KEY constraint 'PK__AP__2EC21549E681BC94'. Cannot insert duplicate key in object 'dbo.Test'. The duplicate key value is (215009). The statement has been terminated.';
INSERT INTO @test SELECT 'Violation of PRIMARY KEY constraint ''PK__AP__2EC21549E681BC94''. Cannot insert duplicate key in object ''dbo.Test''. The duplicate key value is (215009). The statement has been terminated.';
SELECT * FROM @test;

【讨论】:

  • 我不认为它会起作用,因为没有“”的语法会出错,对吧? (PK__...附近的语法不正确)
  • 不,你错了,试试吧……你可能会感到惊讶!基本上它会将' 替换为'',然后SQL Server 将依次将'' 替换回'。它只是告诉查询引擎,当您有 ' 时,将其保存为消息的一部分,而不是将其视为消息的结尾。
  • declare #test nvarchar(255) set #test '违反主键约束'PK__AP__2EC21549E681BC94'。无法在对象“dbo.Test”中插入重复键。重复键值为 (215009)。该语句已终止。'选择替换(#test,'''','''''')错误消息:'违反主键约束'附近的语法不正确。 (用@替换#)
【解决方案2】:

如果该列不支持字符串,那么您将需要 alter 您的 TestLog table 并增加被截断的列的大小。您可以在此处了解如何在 MS SQL 中更改表:

https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-2017

你需要改变你的参数

@ERROR nvarchar(4000)

@ERROR nvarchar(MAX)

此外,您需要查看错误消息的字符数并采取相应措施。

此外,您还需要确保您的引号被正确转义。

【讨论】:

  • 不,抱歉,它不起作用。它可以使用像“hello word”这样的字符串值,甚至可以使用“hello word”,但如果出现“超过 128 个字符长度的随机错误”,SQL 将出错。
  • @Lemon 请向我们展示您的 TestLog 表的结构。
  • 创建表 [dbo].[Process_Log]( [PrimaryName] [nvarchar](255) NULL, [ERROR] [nvarchar](max) NULL )
  • @Lemon 您打算插入表中的主名称多长时间?
  • 现在少于 20 个字符?我认为它不会超过 255 - 只是为了测试。
【解决方案3】:

我找到了解决方案:我必须在执行 SP 之前使用 SET QUOTED_IDENTIFIER OFF 执行 SP,我在我的 SP 中设置了 SET QUOTED_IDENTIFIER OFF - 但每次执行 SP 时都必须执行它。 (SP在软件中执行。)

例子:

SET QUOTED_IDENTIFIER OFF
Exec [TestLog]
@PrimaryName = "test"
,@ERROR = "Violation of PRIMARY KEY constraint 'PK__AP__2EC21549E681BC94'. Cannot insert duplicate key in object 'dbo.Test'. The duplicate key value is (215009).
The statement has been terminated."

那么我会避免一个 128 len 的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 2013-10-08
    • 2014-08-07
    • 1970-01-01
    相关资源
    最近更新 更多