【问题标题】:SQL Server DB Project Publish Empty string inserting a ZeroSQL Server DB 项目发布插入零的空字符串
【发布时间】:2015-03-28 14:47:08
【问题描述】:

当通过 SQL Server 数据库项目发布操作填充数据库中的字段时,我们看到了一个非常奇怪的问题。

这是表定义

CREATE TABLE [dbo].[CatalogueItemExtensionFields] 
(
    [RowID] tinyint identity not null,
    [FieldType] tinyint not null,
    [Description] varchar(120) not null,
    [Nullable] bit not null,
    [DefaultValue] varchar(100) null,
    [Active_Flag] bit null,
    [OrderPriority] tinyint not null,
    [ContextGuid] uniqueidentifier not null
);

这是人口脚本

set identity_insert CatalogueItemExtensionFields on

INSERT INTO CatalogueItemExtensionFields (rowid, fieldtype, description, nullable, defaultvalue, active_flag, orderpriority) 
VALUES (dbo.ConstantProductGroupRowId(), 3, 'Product Group', 0, '', 1, dbo.ConstantProductGroupRowId()),

set identity_insert CatalogueItemExtensionFields off

如果我手动运行INSERT 脚本,一切正常。当我将它作为数据库项目发布的一部分运行时,它会插入“0”。

我查看了生成的publish.sql 脚本,一切正常。

顺便说一句,我发现的唯一类似的帖子是this,但它不适用于我们的案例,因为我们插入的字段被定义为varchar。

这让我们发疯了。有什么想法吗?

【问题讨论】:

  • 在哪里插入 0?那里有 8 列。我相信这些脚本是在 SQLCMD 模式下运行的。所以将 SSMS 设置为 SQLCMD 模式,看看它是否做同样的事情(插入“0”)。当它正常工作时它会做什么? dbo.ConstantProductGroupRowId() 是用户定义的标量函数吗?它看起来像什么?
  • 澄清一下,我正在尝试将空字符串插入“defaultvalue”列。
  • @NickMcDermaid,我们刚刚尝试在 SQLCMD 模式下运行发布脚本,并在尝试写入有效字符串时收到此错误:'Msg 245, Level 16, State 1, Line 7 Conversion failed when convert the varchar 值“测试”到数据类型 int。所以这意味着 SQLCMD 认为该字段是一个 INT,但这不是它在表定义中的显示方式。在 SQLCMD 模式下是否使用了任何晦涩的 DB 设置?
  • 我在您的示例脚本中没有看到“测试”一词。我还在您的 VALUES 子句中看到了一个额外的不需要的尾随逗号。这一切都非常令人困惑。你在这张桌子上有什么触发器吗?这是您正在运行的唯一脚本吗? dbo.ConstantProductGroupRowId() 有什么作用?它返回一个字符串还是一个数字?

标签: sql-server publish default-value varchar


【解决方案1】:

Answer from SqlServerCentral

"空字符串无错误转换为int,其值为0,与隐式转换的先决条件有关"

【讨论】:

    【解决方案2】:

    道歉 - 我的错误! (但是一个非常有用的文档

    我在下面再次总结(也是为了更清楚地尊重我最初的帖子)

    表格定义

    CREATE TABLE [dbo].[CatalogueItemExtensionFields] 
    (
    [RowID] tinyint identity not null,
    [FieldType] tinyint not null,
    [Description] varchar(120) not null,
    [Nullable] bit not null,
    [DefaultValue] varchar(100) null,
    [Active_Flag] bit null,
    [OrderPriority] tinyint not null
    );
    

    插入声明

    set identity_insert CatalogueItemExtensionFields on
    
    INSERT INTO CatalogueItemExtensionFields (rowid, fieldtype, description, nullable, defaultvalue, active_flag, orderpriority) VALUES
    (6, 3, N'Product Group', 0, N'', 1, 6),
    (7, 2, N'Minimum Order Quantity', 1, NULL, 1, 7),
    (8, 3, N'Additional HIBCs', 0, 1, 1, 8),
    (9, 3, N'Additional GTINs', 0, N'', 1, 9)
    
    set identity_insert CatalogueItemExtensionFields off
    

    因为我要插入多行,所以当 SQL 解析它看到的语句时,我试图为 RowID = 8 插入一个数字默认值 = 1。因此,即使该列被定义为 varchar,SQL 也会决定INSERT 语句正在插入 INT。因此,空字符串值(对于 RowID 7 和 9)被转换为零。我提到了我发现的与actual INT column 相关的帖子,这导致了相同的行为。

    如果我改为运行以下语句,RowID = 8 的默认值为“1”,则一切正常。

    INSERT INTO CatalogueItemExtensionFields (rowid, fieldtype, description, nullable, defaultvalue, active_flag, orderpriority) VALUES
    (6, 3, N'Product Group', 0, N'', 1, 6),
    (7, 2, N'Minimum Order Quantity', 1, NULL, 1, 7),
    (8, 3, N'Additional HIBCs', 0, '1', 1, 8),
    (9, 3, N'Additional GTINs', 0, N'', 1, 9)
    

    那么,现在的问题是,为什么 SQL Server 会忽略列类型定义,而是根据我的 INSERT 语句中的值来决定类型?

    【讨论】:

      猜你喜欢
      • 2015-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 2019-02-13
      • 2013-06-05
      • 1970-01-01
      • 2019-11-23
      相关资源
      最近更新 更多