Не удалось включить ограничения. Одна или несколько строк содержат значения, нарушающие ненулевые, уникальные или внешние ключи - PullRequest
153 голосов
/ 11 августа 2011

Я выполняю внешнее соединение и успешно выполняюсь в базе данных informix, но в моем коде получено следующее исключение:

DataTable dt = TeachingLoadDAL.GetCoursesWithEvalState(i, bat);

Не удалось включить ограничения.Одна или несколько строк содержат значения, нарушающие ненулевые, уникальные или ограничения внешнего ключа.

Я знаю проблему, но не знаю, как ее исправить.

Вторая таблица, для которой я выполняю внешнее соединение, содержит составной первичный ключ, который является нулевым в предыдущем запросе внешнего соединения.

РЕДАКТИРОВАТЬ:

    SELECT UNIQUE a.crs_e,  a.crs_e  || '/ ' || a.crst crs_name, b.period,
           b.crscls, c.crsday, c.from_lect, c.to_lect,
           c.to_lect - c.from_lect + 1 Subtraction, c.lect_kind, e.eval, e.batch_no,
           e.crsnum, e.lect_code, e.prof_course
    FROM rlm1course a, rfc14crsgrp b, ckj1table c, mnltablelectev d,
         OUTER(cc1assiscrseval e)  
    WHERE a.crsnum = b.crsnum 
    AND b.crsnum = c.crsnum 
    AND b.crscls = c.crscls 
    AND b.batch_no = c.batch_no 
    AND c.serial_key = d.serial_key  
    AND c.crsnum = e.crsnum  
    AND c.batch_no = e.batch_no  
    AND d.lect_code= e.lect_code 
    AND d.lect_code = .... 
    AND b.batch_no = ....

Проблема возникаетсо столом cc1assiscrseval.Первичный ключ (batch_no, crsnum, lect_code).

Как решить эту проблему?


РЕДАКТИРОВАТЬ:

Согласно @PaulStock совет: я делаю то, что он сказал, и я получаю:

?dt.GetErrors () [0] {System.Data.DataRow} HasErrors: true ItemArray: {object [10]} RowError: «Столбец 'eval' не допускает DBNull.Value."

Поэтому я решаю свою проблему, заменяя e.eval на NVL (e.eval,'') eval., И это решает мою проблему.Большое спасибо.

Ответы [ 22 ]

314 голосов
/ 11 августа 2011

Эта проблема обычно вызывается одним из следующих

  • нулевых значений, возвращаемых для столбцов, для которых не установлено AllowDBNull
  • повторяющихся строк, возвращаемых с тем же первичным ключом.
  • несоответствие в определении столбца (например, размер полей символов) между базой данных и набором данных

Попробуйте выполнить собственный запрос и посмотрите на результаты, если набор результатов не слишком велик.Если вы удалили нулевые значения, то я предполагаю, что столбцы первичного ключа дублируются.

Или, чтобы увидеть точную ошибку, вы можете вручную добавить блок Try / Catch в сгенерированный код, например, так:и затем прерывание при возникновении исключения:

enter image description here

Затем в командном окне вызовите метод GetErrors для таблицы, получая ошибку.
Для C # командабудет ? dataTable.GetErrors()
Для VB, команда будет ? dataTable.GetErrors

enter image description here

Это покажет вам все datarows, которые имеют ошибку.Затем вы можете посмотреть на RowError для каждого из них, который должен указать вам недопустимый столбец вместе с проблемой.Итак, чтобы увидеть ошибку первого datarow в ошибке, введите команду:
? dataTable.GetErrors(0).RowError
или в C # это будет ? dataTable.GetErrors()[0].RowError

enter image description here

35 голосов
/ 08 августа 2012

Вы можете отключить ограничения для набора данных. Это позволит вам идентифицировать неверные данные и поможет решить проблему.

например.

dataset.TableA.Clear();
dataset.EnforceConstraints = false;
dataAdapter1.daTableA.Fill(dataset, TableA");

Способ заполнения может немного отличаться для вас.

8 голосов
/ 03 июня 2013

Это найдет все строки в таблице с ошибками, распечатает первичный ключ строки и ошибку, которая произошла в этой строке ...

Это в C #, но преобразование его в VB не должнобыть жестким.

 foreach (DataRow dr in dataTable)
 {
   if (dr.HasErrors)
     {
        Debug.Write("Row ");
        foreach (DataColumn dc in dataTable.PKColumns)
          Debug.Write(dc.ColumnName + ": '" + dr.ItemArray[dc.Ordinal] + "', ");
        Debug.WriteLine(" has error: " + dr.RowError);
     }
  }

Упс. Извините, PKColumns - это то, что я добавил, когда расширил DataTable, который сообщает мне все столбцы, которые составляют первичный ключ DataTable.Если вы знаете столбцы первичного ключа в таблице данных, вы можете просмотреть их здесь.В моем случае, поскольку все мои таблицы данных знают свои столбцы PK, я могу автоматически написать отладку для этих ошибок для всех таблиц.

Вывод выглядит так:

Row FIRST_NAME: 'HOMER', LAST_NAME: 'SIMPSON', MIDDLE_NAME: 'J',  has error: Column 'HAIR_COLOR' does not allow DBNull.Value.
7 голосов
/ 18 апреля 2012
  • Убедитесь, что поля, указанные в запросе адаптера таблицы, совпадают с полями в заданном вами запросе.DAL, похоже, не любит несоответствия.Обычно это происходит с вашими спрочами и запросами после добавления нового поля в таблицу.

  • Если вы изменили длину поля varchar в базе данных, а XML, содержащийся в файле XSS, не обнаружил ее, найдите имя поля и определение атрибута в XML иизмените это вручную.

  • Удалите первичные ключи из списков выбора в адаптерах таблиц, если они не связаны с возвращаемыми данными.

  • Запустите запрос в SQL Management Studio и убедитесь, что не возвращаются повторяющиеся записи.Дублирующиеся записи могут генерировать дубликаты первичных ключей, что приведет к этой ошибке.

  • Союзы SQL могут означать проблемы.Я изменил один адаптер таблицы, добавив запись «Пожалуйста, выберите сотрудника», предшествующую другим.Для других полей я предоставил фиктивные данные, в том числе, например, строки длиной один.DAL выводит схему из этой начальной записи.Записи, следующие со строками длиной 12 не удалось.

5 голосов
/ 26 декабря 2012

Это сработало для меня, источник: здесь

У меня была эта ошибка, и она не была связана с ограничениями БД (по крайней мере, в моем случае). У меня есть файл .xsd с запросом GetRecord, который возвращает группу записей. Один из столбцов этой таблицы был «nvarchar (512)», и в середине проекта мне нужно было изменить его на «nvarchar (MAX)».

Все работало нормально, пока пользователь не ввел более 512 в это поле, и мы не начали получать известное сообщение об ошибке «Не удалось включить ограничения. Одна или несколько строк содержат значения, нарушающие ограничения ненулевого, уникального или внешнего ключа. «

Решение. Проверьте все свойства MaxLength столбцов в DataTable.

Столбец, который я изменил с "nvarchar (512)" на "nvarchar (MAX)", все еще имел значение 512 для свойства MaxLength, поэтому я изменил на "-1", и это работает !!

4 голосов
/ 25 ноября 2015

Проблема с конструктором доступа к данным.В Visual Studio, когда мы извлекаем представление из «обозревателя сервера» в окно «Конструктор», он добавляет либо первичный ключ в столбце случайным образом, либо помечает что-то в NOT NULL, хотя на самом деле для него установлено значение NULL.Несмотря на то, что фактическое создание View на сервере базы данных SQL не имеет ни первичного ключа, ни определенного NOT NULL, конструктор VS добавляет этот ключ / ограничение.

Вы можете увидеть это в конструкторе - этоотображается со значком ключа слева от названия столбца.

Решение: Щелкните правой кнопкой мыши значок ключа и выберите «Удалить ключ».Это должно решить проблему.Вы также можете щелкнуть правой кнопкой мыши по столбцу и выбрать «Свойства», чтобы увидеть список свойств столбца в конструкторе доступа к данным VS и соответствующим образом изменить значения.

3 голосов
/ 07 ноября 2012

Эта ошибка также отображалась в моем проекте. Я попробовал все предложенные решения, опубликованные здесь, но не повезло, потому что проблема не имела ничего общего с размером полей, определением полей таблицы ключей, ограничениями или переменной набора данных EnforceConstraints.

В моем случае у меня также есть объект .xsd, который я поместил туда во время разработки проекта (Уровень доступа к данным). При перетаскивании объектов таблицы базы данных в визуальный элемент набора данных он считывает каждое определение таблицы из базовой базы данных и копирует ограничения в объект набора данных в точности так, как вы их определили при создании таблиц в вашей базе данных (SQL Server 2008 R2 в моем дело). Это означает, что каждый столбец таблицы, созданный с ограничением «not null» или «external key», также должен присутствовать в результате вашего оператора SQL или хранимой процедуры.

После того как я включил в свои запросы все ключевые столбцы и столбцы, определенные как «не нулевые», проблема полностью исчезла.

3 голосов
/ 10 апреля 2015

Мой начал работать, когда я установил AllowDBNull в True для поля даты в таблице данных в файле xsd.

2 голосов
/ 13 августа 2011

Непонятно, почему выполнение оператора SELECT должно включать в себя включающие ограничения. Я не знаю C # или связанных технологий, но я знаю базу данных Informix. В системе происходит что-то странное, если ваш код запроса включает (и, вероятно, также отключает) ограничения.

Вам также следует избегать устаревшей нестандартной нотации Informix OUTER join. Если вы не используете невероятно старую версию Informix, вы должны использовать стиль соединений SQL-92.

В вашем вопросе упоминаются два внешних объединения, но в примере запроса вы показываете только одно. Это тоже немного озадачивает.

Условия соединения между 'e' и остальными таблицами:

AND c.crsnum = e.crsnum  
AND c.batch_no = e.batch_no  
AND d.lect_code= e.lect_code 

Это необычная комбинация. Поскольку у нас нет соответствующего подмножества схемы с соответствующими ограничениями ссылочной целостности, трудно понять, является ли это правильным или нет, но несколько необычно объединять такие 3 таблицы.

Ничто из этого не является окончательным решением вашей проблемы; Тем не менее, он может дать некоторые рекомендации.

2 голосов
/ 05 мая 2014

Спасибо за все, что было сделано до сих пор.Я просто хочу добавить, что, хотя можно успешно нормализовать БД, обновить любые изменения схемы в своем приложении (например, в наборе данных) или около того, есть и другая причина: sql CARTESIAN product (при объединении таблиц в запросах).

Наличие результата декартового запроса приведет к дублированию записей в первичной (или первой по ключу) таблице двух или более таблиц, которые будут объединены.Даже если вы зададите условие «Где» в SQL, декартово число может все же произойти, если, например, JOIN с вторичной таблицей содержит неравное соединение (полезно, когда для получения данных из 2 или более несвязанных таблиц):

ОТ ВНУТРЕННЕГО СОЕДИНЕНИЯ tbFirst ВКЛ tbSystem ВКЛ tbFirst.reference_str <> tbSystem.systemKey_str

Решение для этого: таблицы должны быть связаны.

Спасибо.chagbert

...