webentwicklung-frage-antwort-db.com.de

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

Ich verwende die Datei data.bat mit den folgenden Zeilen:

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 start> run> cmd> c:\data.bat ausführen, erhalte ich folgende 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 bedeuten Level # und state # und wie schaue ich in Fehlermeldungen wie der oben genannten: 8152?

206
karthik

Aus @ gmmastros's Antwort

Wann immer Sie die Nachricht sehen ....

string or binary data would be truncated 

Denken Sie an sich 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 Telefonfeld beispielsweise ein Feld varchar (8) ist und Sie versuchen, 11 Zeichen einzugeben, wird diese Fehlermeldung angezeigt. 

538
karthik

In einer der INSERT-Anweisungen versuchen Sie, eine zu lange Zeichenfolge in eine Zeichenfolgenspalte (varchar oder nvarchar) einzufügen.

Wenn es nicht offensichtlich ist, welche INSERT durch einen bloßen Blick auf das Skript der Täter ist, könnten Sie die <1 row affected>-Zeilen zählen, die vor der Fehlermeldung vorkommen. Die ermittelte Zahl plus Eins gibt die Anweisungsnummer an. In Ihrem Fall scheint es die zweite INSERT zu sein, die den Fehler erzeugt.

18
Andriy M

Ich hatte dieses Problem, obwohl die Datenlänge kürzer war als die Feldlänge ..__ Es stellte sich heraus, dass das Problem darin bestand, eine andere Protokolltabelle (für Prüfprotokoll) zu haben, die durch einen Auslöser in der Haupttabelle gefüllt wurde, wobei auch die Spaltengröße erforderlich war verändert sein.

17
alterfox

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 zunächst 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 einen globalen Ausnahmebehandler vor und protokollieren Sie Details zum Abschneiden:

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

Verwenden Sie schließlich den Code:

Datamodel.SubmitChangesWithDetailException();
11
Tomas Kubes

Eine andere Situation, in der Sie diesen Fehler erhalten können, ist 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 sich von der ursprünglichen Tabelle unterschied. 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
hola77

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

ABER es ist sehr wichtig zu wissen, was die möglichen Gründe dafür sind.

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

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

Daher hatte das Feld "Periode" eine Länge von Null und die Einfügeoperationen schlagen fehl. 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
RaRdEvA

War dieses Problem auch auf der Webanwendungsoberfläche aufgetreten. Schließlich wurde herausgefunden, dass dieselbe Fehlermeldung von der SQL-Aktualisierungsanweisung in der jeweiligen Tabelle stammt. 

Schließlich stellte sich heraus, dass die Colum-Definition in den zugehörigen Historientabellen in bestimmten Fällen nicht die ursprüngliche Spaltenlänge der nvarchar-Typen zugeordnet hat.  

Ich hoffe, dieser Hinweis hilft auch jemand anderem.;) 

7
webMac

auf SQL Server können Sie SET ANSI_WARNINGS OFF wie folgt 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
Esperento57

Ich hatte das gleiche Problem .. _. Die Länge meiner Kolonne war zu kurz . Was Sie tun können, ist entweder Zunahme die Länge oder (Kürzel den Text, den Sie in die Datenbank aufnehmen möchten.

6
user2983359

Beim Versuch, meine gespeicherte Prozedur auszuführen, hatte ich das gleiche Problem, da die Größe der Spalte, die ich zum Hinzufügen einiger Daten benötige, kürzer ist als die Daten, die ich hinzufügen möchte. Sie können die Größe des Spaltendatentyps erhöhen oder die Länge Ihrer Daten verringern.

1

Eine andere Situation, in der dieser Fehler auftreten kann, ist in SQL Server Management Studio. Wenn Sie "Text" - oder "Ntext" -Felder in Ihrer Tabelle haben, Unabhängig davon, welche Art von Feld Sie aktualisieren (zum Beispiel Bit oder Integer) . Das Studio lädt nicht die gesamten "Ntext" -Felder und aktualisiert auch ALLE Felder anstelle des geänderten Feldes ..__ Um das Problem zu lösen, schließen Sie die Felder "Text" oder "Ntext" aus der Abfrage in Management Studio aus

1
Sevast

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 entsprechenden Tabellentypen muss möglicherweise ebenfalls erhöht werden.

In meinem Fall kam der Fehler vom Datenexportdienst in Microsoft Dynamics CRM, wodurch 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 Tabellenwertparameter verwenden muss:

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

Wie Sie in der Dokumentation oben sehen können, werden zur Erstellung des Datenaufnahmeverfahrens Tabellentypen verwendet:

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

Leider gibt es keine Möglichkeit, einen Tabellentyp zu ändern. Daher muss er vollständig gelöscht und neu erstellt werden. Da meine Tabelle über 300 Felder hat (????), habe ich eine Abfrage erstellt, um die Erstellung des entsprechenden Tabellentyps basierend auf der Tabellendefinition der Tabelle zu erleichtern (ersetzen Sie einfach [table_name] 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 einwandfrei! :)

0
Marco Roy