Fehler-, Zeichenfolgen- oder Binärdaten werden beim Einfügen abgeschnitten


250

Ich führe die Datei data.bat mit den folgenden Zeilen aus:

Rem Tis batch file will populate tables

cd\program files\Microsoft SQL Server\MSSQL
osql -U sa -P Password -d MyBusiness -i c:\data.sql

Der Inhalt der Datei data.sql lautet:

   insert Customers
            (CustomerID, CompanyName, Phone)
             Values('101','Southwinds','19126602729')

Es gibt 8 weitere ähnliche Zeilen zum Hinzufügen von Datensätzen.

Wenn ich dies mit laufen start> run> cmd> c:\data.bat, erhalte ich diese Fehlermeldung:

1>2>3>4>5>....<1 row affected>
Msg 8152, Level 16, State 4, Server SP1001, Line 1
string or binary data would be truncated.

<1 row affected>

<1 row affected>

<1 row affected>

<1 row affected>

<1 row affected>

<1 row affected>

Ich bin natürlich auch ein Neuling, aber was tun Level #und state #bedeuten und wie suche ich nach Fehlermeldungen wie der oben genannten: 8152?

Antworten:


609

Aus der Antwort von @ gmmastros

Wann immer Sie die Nachricht sehen ....

String oder Binärdaten würden abgeschnitten werden

Denken Sie selbst ... Das Feld ist NICHT groß genug, um meine Daten zu speichern.

Überprüfen Sie die Tabellenstruktur für die Kundentabelle. Ich denke, Sie werden feststellen, dass die Länge eines oder mehrerer Felder NICHT groß genug ist, um die Daten aufzunehmen, die Sie einfügen möchten. Wenn das Feld Telefon beispielsweise ein varchar (8) -Feld ist und Sie versuchen, 11 Zeichen einzugeben, wird dieser Fehler angezeigt.


16
Beachten Sie auch, dass sich die betroffenen Felder in einem Trigger befinden können. Hoffentlich erinnere ich mich daran, wenn dies das nächste Mal passiert ...
Kevin Pope

14
Gibt es eine Möglichkeit, beim Debuggen zu sehen, welches Feld abgeschnitten wird?
DailyFrankPeter

Dieser Fehler liegt daran, dass Ihre Spalte nach der von Ihnen festgelegten Länge keine Daten mehr enthalten kann. Z.B; Firstname nvarchar(5) Wenn Sie mehr als 5 Zeichen einfügen, erhalten Sie den Fehler
Prakash

26

Ich hatte dieses Problem, obwohl die Datenlänge kürzer als die Feldlänge war. Es stellte sich heraus, dass das Problem darin bestand, dass eine andere Protokolltabelle (für den Prüfpfad) mit einem Trigger in der Haupttabelle gefüllt war, in der auch die Spaltengröße geändert werden musste.


1
Vielen Dank. Meins war, weil die SQL-Spalte in Tabelle A varchar (100) ist. Es wird auch in eine andere Tabelle eingefügt, in der die Spalte varchar (50) lautet.
Hnin Htet Htet Aung

1
Das gleiche Problem trat auch in meinem Fall auf. Eine Triggeroperation war der Schuldige.
Autopilot

19

In einer der INSERTAnweisungen versuchen Sie, eine zu lange Zeichenfolge in eine Zeichenfolge ( varcharoder nvarchar) -Spalte einzufügen .

Wenn es nicht INSERTdurch einen Blick auf das Skript offensichtlich ist, welcher der Täter ist, können Sie die <1 row affected>Zeilen zählen, die vor der Fehlermeldung auftreten. Die erhaltene Nummer plus eins gibt Ihnen die Anweisungsnummer. In Ihrem Fall scheint es das zweite INSERT zu sein, das den Fehler erzeugt.


2
Ich habe das gleiche Problem, wie finde ich heraus, welche Spalte den Fehler verursacht?
Cátia Matos

@ AndréBastos: Vielleicht könnten Sie das als Frage einreichen (es sei denn, jemand anderes hat das bereits getan, in diesem Fall gibt es möglicherweise irgendwo eine fertige Antwort darauf).
Andriy M

11

Einige Ihrer Daten passen nicht in Ihre Datenbankspalte (klein). Es ist nicht leicht zu finden, was falsch ist. Wenn Sie C # und Linq2Sql verwenden, können Sie das Feld auflisten, das abgeschnitten werden würde:

Erstellen Sie zuerst eine Hilfsklasse:

public class SqlTruncationExceptionWithDetails : ArgumentOutOfRangeException
{
    public SqlTruncationExceptionWithDetails(System.Data.SqlClient.SqlException inner, DataContext context)
        : base(inner.Message + " " + GetSqlTruncationExceptionWithDetailsString(context))
    {
    }

    /// <summary>
    /// PArt of code from following link
    /// http://stackoverflow.com/questions/3666954/string-or-binary-data-would-be-truncated-linq-exception-cant-find-which-fiel
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    static string GetSqlTruncationExceptionWithDetailsString(DataContext context)
    {
        StringBuilder sb = new StringBuilder();

        foreach (object update in context.GetChangeSet().Updates)
        {
            FindLongStrings(update, sb);
        }

        foreach (object insert in context.GetChangeSet().Inserts)
        {
            FindLongStrings(insert, sb);
        }
        return sb.ToString();
    }

    public static void FindLongStrings(object testObject, StringBuilder sb)
    {
        foreach (var propInfo in testObject.GetType().GetProperties())
        {
            foreach (System.Data.Linq.Mapping.ColumnAttribute attribute in propInfo.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), true))
            {
                if (attribute.DbType.ToLower().Contains("varchar"))
                {
                    string dbType = attribute.DbType.ToLower();
                    int numberStartIndex = dbType.IndexOf("varchar(") + 8;
                    int numberEndIndex = dbType.IndexOf(")", numberStartIndex);
                    string lengthString = dbType.Substring(numberStartIndex, (numberEndIndex - numberStartIndex));
                    int maxLength = 0;
                    int.TryParse(lengthString, out maxLength);

                    string currentValue = (string)propInfo.GetValue(testObject, null);

                    if (!string.IsNullOrEmpty(currentValue) && maxLength != 0 && currentValue.Length > maxLength)
                    {
                        //string is too long
                        sb.AppendLine(testObject.GetType().Name + "." + propInfo.Name + " " + currentValue + " Max: " + maxLength);
                    }

                }
            }
        }
    }
}

Bereiten Sie dann den Wrapper für SubmitChanges vor:

public static class DataContextExtensions
{
    public static void SubmitChangesWithDetailException(this DataContext dataContext)
    {
        //http://stackoverflow.com/questions/3666954/string-or-binary-data-would-be-truncated-linq-exception-cant-find-which-fiel
        try
        {
            //this can failed on data truncation
            dataContext.SubmitChanges();
        }       
        catch (SqlException sqlException) //when (sqlException.Message == "String or binary data would be truncated.")
        {

            if (sqlException.Message == "String or binary data would be truncated.") //only for EN windows - if you are running different window language, invoke the sqlException.getMessage on thread with EN culture
                throw new SqlTruncationExceptionWithDetails(sqlException, dataContext);
            else
                throw;
        }
    }
}

Bereiten Sie Details zum globalen Ausnahmebehandler und zum Abschneiden von Protokollen vor:

protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    string message = ex.Message;
    //TODO - log to file
}

Verwenden Sie zum Schluss den Code:

Datamodel.SubmitChangesWithDetailException();

9

Ich möchte nur mit zusätzlichen Informationen beitragen: Ich hatte das gleiche Problem und es war, weil das Feld nicht groß genug für die eingehenden Daten war und dieser Thread mir half, es zu lösen (die oberste Antwort verdeutlicht alles).

ABER es ist sehr wichtig zu wissen, was die möglichen Gründe sind, die es verursachen können.

In meinem Fall habe ich die Tabelle mit einem Feld wie dem folgenden erstellt:

Select '' as  Period, * From Transactions Into #NewTable

Daher hatte das Feld "Periode" eine Länge von Null und führte dazu, dass die Einfügevorgänge fehlschlugen. Ich habe es in "XXXXXX" geändert, das ist die Länge der eingehenden Daten und es hat jetzt richtig funktioniert (weil das Feld jetzt eine Länge von 6 hatte).

Ich hoffe das hilft jedem mit dem gleichen Problem :)


7

Eine andere Situation, in der Sie diesen Fehler erhalten können, ist die folgende:

Ich hatte den gleichen Fehler und der Grund war, dass in einer INSERT-Anweisung, die Daten von einer UNION erhielt, die Reihenfolge der Spalten von der ursprünglichen Tabelle abweicht. Wenn Sie die Reihenfolge in # table3 in a, b, c ändern, wird der Fehler behoben.

select a, b, c into #table1
from #table0

insert into #table1
    select a, b, c from #table2
    union
    select a, c, b from #table3

7

Auf einem SQL Server können Sie SET ANSI_WARNINGS OFF folgendermaßen verwenden:

        using (SqlConnection conn = new SqlConnection("Data Source=XRAYGOAT\\SQLEXPRESS;Initial Catalog='Healthy Care';Integrated Security=True"))
        {
            conn.Open();

            using (var trans = conn.BeginTransaction())
            {
                try
                {
                    using cmd = new SqlCommand("", conn, trans))
                    { 

                    cmd.CommandText = "SET ANSI_WARNINGS OFF";
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = "YOUR INSERT HERE";
                    cmd.ExecuteNonQuery();

                    cmd.Parameters.Clear();

                    cmd.CommandText = "SET ANSI_WARNINGS ON";
                    cmd.ExecuteNonQuery();

                    trans.Commit();
                    }
                }
                catch (Exception)
                {

                    trans.Rollback();
                }

            }

            conn.Close();

        }

7

Ich hatte das gleiche Problem. Die Länge meiner Kolumne war zu kurz.

Sie können entweder die Länge erhöhen oder den Text verkürzen, den Sie in die Datenbank einfügen möchten.


7

Auch dieses Problem trat auf der Webanwendungsoberfläche auf. Schließlich stellte sich heraus, dass dieselbe Fehlermeldung von der SQL-Aktualisierungsanweisung in der spezifischen Tabelle stammt.

Schließlich stellte sich heraus, dass die Spaltendefinition in den zugehörigen Verlaufstabellen nvarcharin einigen bestimmten Fällen nicht die ursprüngliche Tabellenspaltenlänge der Typen abbildete .


4

Ich hatte das gleiche Problem, auch nachdem ich die problematischen Spalten in der Tabelle vergrößert hatte.

tl; dr: Die Länge der übereinstimmenden Spalten in den entsprechenden Tabellentypen muss möglicherweise ebenfalls erhöht werden.

In meinem Fall kam der Fehler vom Datenexportdienst in Microsoft Dynamics CRM, mit dem CRM-Daten mit einer SQL Server-Datenbank oder einer Azure SQL-Datenbank synchronisiert werden können.

Nach einer langen Untersuchung kam ich zu dem Schluss, dass der Datenexportdienst tabellenwertige Parameter verwenden muss :

Sie können tabellenwertige Parameter verwenden, um mehrere Datenzeilen an eine Transact-SQL-Anweisung oder eine Routine zu senden, z. B. eine gespeicherte Prozedur oder Funktion, ohne eine temporäre Tabelle oder viele Parameter zu erstellen.

Wie Sie in der obigen Dokumentation sehen können, werden Tabellentypen verwendet, um das Datenaufnahmeverfahren zu erstellen:

CREATE TYPE LocationTableType AS TABLE (...);
CREATE PROCEDURE dbo.usp_InsertProductionLocation
  @TVP LocationTableType READONLY

Leider gibt es keine Möglichkeit, einen Tabellentyp zu ändern, sodass er gelöscht und vollständig neu erstellt werden muss. Da meine Tabelle über 300 Felder (😱) enthält, habe ich eine Abfrage erstellt, um die Erstellung des entsprechenden Tabellentyps basierend auf der Spaltendefinition der Tabelle zu erleichtern (ersetzen [table_name]Sie sie einfach durch den Namen Ihrer Tabelle):

SELECT 'CREATE TYPE [table_name]Type AS TABLE (' + STRING_AGG(CAST(field AS VARCHAR(max)), ',' + CHAR(10)) + ');' AS create_type
FROM (
  SELECT TOP 5000 COLUMN_NAME + ' ' + DATA_TYPE
      + IIF(CHARACTER_MAXIMUM_LENGTH IS NULL, '', CONCAT('(', IIF(CHARACTER_MAXIMUM_LENGTH = -1, 'max', CONCAT(CHARACTER_MAXIMUM_LENGTH,'')), ')'))
      + IIF(DATA_TYPE = 'decimal', CONCAT('(', NUMERIC_PRECISION, ',', NUMERIC_SCALE, ')'), '')
      AS field
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_NAME = '[table_name]'
  ORDER BY ORDINAL_POSITION) AS T;

Nach dem Aktualisieren des Tabellentyps funktionierte der Datenexportdienst wieder ordnungsgemäß! :) :)


2

Als ich versuchte, meine gespeicherte Prozedur auszuführen, hatte ich das gleiche Problem, da die Größe der Spalte, in der ich einige Daten hinzufügen muss, kürzer ist als die Daten, die ich hinzufügen möchte.

Sie können den Spaltendatentyp vergrößern oder die Länge Ihrer Daten verringern.


1

Eine andere Situation, in der dieser Fehler auftreten kann, ist in SQL Server Management Studio. Wenn Ihre Tabelle "Text" - oder "ntext" -Felder enthält, unabhängig davon, welche Art von Feld Sie aktualisieren (z. B. Bit oder Ganzzahl). Es scheint, dass das Studio nicht ganze "ntext" -Felder lädt und statt des geänderten auch ALLE Felder aktualisiert. Um das Problem zu lösen, schließen Sie die Felder "Text" oder "ntext" von der Abfrage in Management Studio aus


1
Bitte überlegen Sie, Ihre Antwort neu zu formulieren, indem Sie Kommas und Punkte hinzufügen und Ihre Grammatikfehler beheben.
George Pamfilis

Diese Antwort hat mir geholfen - meine nvarchar-Felder sind groß genug, aber ich habe ein ntext-Feld. Scheint ein Fehler in Management Studio / SMSS zu sein.
Sha

0

Kevin Popes Kommentar unter der akzeptierten Antwort war das, was ich brauchte.

In meinem Fall bestand das Problem darin, dass in meiner Tabelle Trigger definiert waren, die Aktualisierungs- / Einfügungstransaktionen in eine Prüftabelle einfügen, die Prüftabelle jedoch eine Datentypinkongruenz aufwies, bei der eine Spalte mit VARCHAR(MAX)in der ursprünglichen Tabelle wie VARCHAR(1)in der Tabelle gespeichert wurde Audit-Tabelle, daher schlugen meine Trigger fehl, wenn ich etwas Größeres als VARCHAR(1)in die ursprüngliche Tabellenspalte einfügte und diese Fehlermeldung erhielt.


0

Ich habe eine andere Taktik angewendet, Felder, denen an einigen Stellen 8 KB zugewiesen sind. Hier werden nur ca. 50/100 verwendet.

declare @NVPN_list as table 
nvpn            varchar(50)
,nvpn_revision  varchar(5)
,nvpn_iteration INT
,mpn_lifecycle  varchar(30)
,mfr            varchar(100)
,mpn            varchar(50)
,mpn_revision   varchar(5)
,mpn_iteration  INT
-- ...
) INSERT INTO @NVPN_LIST 
SELECT  left(nvpn           ,50)    as nvpn
        ,left(nvpn_revision ,10)    as nvpn_revision
        ,nvpn_iteration
        ,left(mpn_lifecycle ,30)
        ,left(mfr           ,100)
        ,left(mpn           ,50)
        ,left(mpn_revision  ,5)
        ,mpn_iteration
        ,left(mfr_order_num ,50)
FROM [DASHBOARD].[dbo].[mpnAttributes] (NOLOCK) mpna

Ich wollte Geschwindigkeit, da ich insgesamt 1 Million Datensätze habe und 28 KB davon lade.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.