select union创建的返回表中的重复主键

时间:2012-02-28 20:18:37

标签: tsql datatable constraints union query-builder

我有以下名为searchit的查询

SELECT 2 AS sourceID, BLOG_COMMENTS.bID, BLOG_TOPICS.Topic_Title,
    BLOG_TOPICS.LFD, BLOG_TOPICS.LC,
    BLOG_COMMENTS.Comment_Narrative
FROM BLOG_COMMENTS INNER JOIN BLOG_TOPICS
    ON BLOG_COMMENTS.bID = BLOG_TOPICS.bID
WHERE  (BLOG_COMMENTS.Comment_Narrative LIKE @Phrase)

此查询执行AND在查询构建器中返回正确的结果! 但是,查询需要在代码隐藏中运行,所以我有以下几行:

DataTable blogcomments = btad.searchit(aphrase);

表中的任何列的任何行中都没有空字段。表格足够小我可以轻松检测到空数据。请注意,bID是blog_topics的关键,cID是博客评论的关键。

无论如何,当我运行时,我收到以下错误:

  

无法启用约束。一行或多行包含值   违反非空,唯一或外键约束。

表格有1 x N关系,每个博客条目都有很多评论。如果我使用DISTINCT运行查询并从返回字段中删除Comment_Narrative,它会正确返回数据(但我需要其他行!)但是,当我返回其他行时,我收到上述错误!

我想我告诉我,返回表上存在一个我没有放在那里的约束,因此它必须以某种方式从查询本身的调用继承该约束,因为其中一个表恰好定义了主键(它必须有)。但是为什么查询在querybuilder中工作正常呢?查询构建器并不关心bID是否在结果中被欺骗(并且它不应该被欺骗),但是代码隐藏在关注。

附录:

就像测试一样,

  1. 我从返回列表中删除了bID,但仍然收到错误。
  2. 我从blog_topics.bID中删除了主键,但我得到了同样的错误。
  3. 这有点告诉我,我的bID不是导致问题的事实。

    另一项测试: 我进入了设计师代码(我知道它很讨厌,我只是绝望)。 我添加了以下内容:

        // zzz
        try
        {
    
            this.Adapter.Fill(dataTable);
        }
        catch ( global::System.Exception ex )
        {
    
        }
    

    奇怪的是,当我运行它时,我得到了和以前一样的错误并且它没有显示我在错误消息中所做的更改:

    Line 13909:            }
    Line 13910:            BPLL_Dataset.BLOG_TOPICSDataTable dataTable = new BPLL_Dataset.BLOG_TOPICSDataTable();
    Line 13911:            this.Adapter.Fill(dataTable);
    Line 13912:            return dataTable;
    Line 13913:        }
    

    我很难过......除非它看到我在try catch中没有做任何事情并且正在为我进行优化。

    另一个附录: 怀疑它忽略了我添加到设计器中的测试代码,我在catch中添加了一些东西。它产生SAME错误,并且表现得像看不到这段代码。 (好吧,好吧,它没有看到这段代码,因为它打印出的内容与以前一样打印到浏览器中。)

        // zzz
        try
        {
    
            this.Adapter.Fill(dataTable);
        }
        catch ( global::System.Exception ex )
        {
            System.Web.HttpContext.Current.Response.Redirect("errorpage.aspx");
        }
    

    问题是,当我发布原始帖子时,我总是试图解决这个问题。我不知道我能走多远才能走下兔子洞。也许我把整个混乱都读成C#并自己做所有的连接和废话。我真的讨厌这样做,因为我最近才摆脱了这个习惯,但我觉得我正在努力按照上帝和微软的意图使用这个工具。从机智的结束,tff。

2 个答案:

答案 0 :(得分:1)

你没有真正展示你是如何从C#运行这个查询的......但是我假设它是SqlCommand中的直接文本,或者是由某些ORM完成的...你试过写这个查询吗?作为存储过程并以这种方式调用它?存储过程将更容易测试并自行运行样本数据。

鉴于错误提到空值我会假设,如果它是查询的问题而不是代码的其他元素,那么它必须位于以下字段之一: BLOG_COMMENTS.bID BLOG_TOPICS.bID BLOG_COMMENTS.Comment_Narrative

如果这些字段中的任何一个是Nullable,那么在进行任何比较或加入之前,你应该对它们进行COALESCE或ISNULL。正是这些情况解释了为什么大多数DBA希望在表中尽可能少的可空列 - 它们会导致开销并且容易出错。

如果仍然无法解决您的问题,那么COALESCE / ISNULL可以为空并且此查询返回的所有字段。从等式中取出所有空值,然后让事情正常工作,然后,如果你真的需要空值为null,请返回并一次删除一个COALESCE / ISNULL,直到找到罪魁祸首。

答案 1 :(得分:0)

我的问题来自于无知和一点沉闷。我没有意识到这只是因为字段是sql表中的键确实意味着它必须是tableadapter中的键。如果有一个在SQL表中定义的键字段然后创建表适配器,则适配器中的相应字段也将是一个键。我所要做的就是取消设置tableadapter中的关键字段并且它有效。

解决方案:

  • 选择适配器中的关键字段。
  • 右键单击
  • 选择“删除密钥”(保留字段,但删除“密钥”图标)

就是这样。