kesalahan, string atau data biner akan terpotong saat mencoba memasukkan

250

Saya menjalankan file data.bat dengan baris berikut:

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

Isi file data.sql adalah:

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

Ada 8 baris yang lebih mirip untuk menambahkan catatan.

Ketika saya menjalankan ini dengan start> run> cmd> c:\data.bat, saya mendapatkan pesan kesalahan ini:

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>

Saya juga seorang pemula, tetapi apa yang harus dilakukan Level #, dan apa state #artinya, dan bagaimana cara mencari pesan kesalahan seperti di atas: 8152?

karthik
sumber

Jawaban:

609

Dari jawaban @ gmmastros

Setiap kali Anda melihat pesan ....

string atau data biner akan terpotong

Pikirkan sendiri ... Bidang ini TIDAK cukup besar untuk menampung data saya.

Periksa struktur tabel untuk tabel pelanggan. Saya pikir Anda akan menemukan bahwa panjang satu atau lebih bidang TIDAK cukup besar untuk menampung data yang Anda coba masukkan. Misalnya, jika bidang Telepon adalah bidang varchar (8), dan Anda mencoba memasukkan 11 karakter ke dalamnya, Anda akan mendapatkan kesalahan ini.

karthik
sumber
16
Perhatikan juga bahwa bidang yang terpengaruh bisa menjadi pemicu. Semoga saya ingat ini saat berikutnya terjadi ...
Kevin Pope
14
Apakah ada cara untuk melihat di debug bidang mana yang akan terpotong?
DailyFrankPeter
Kesalahan ini karena kolom Anda tidak dapat menyimpan data setelah lama Anda memperbaiki. Misalnya; Firstname nvarchar(5) Jika Anda memasukkan lebih dari 5 karakter, Anda akan mendapatkan kesalahan
Prakash
26

Saya memiliki masalah ini meskipun panjang data lebih pendek dari panjang bidang. Ternyata masalahnya adalah memiliki tabel log lain (untuk jejak audit), diisi oleh pemicu di tabel utama, di mana ukuran kolom juga harus diubah.

alterfox
sumber
1
Terima kasih. Milik saya karena kolom sql di tableA adalah varchar (100). Itu juga menyisipkan ke tabel lain, di mana, kolomnya adalah varchar (50).
Hnin Htet Htet Aung
1
Masalah yang sama terjadi pada kasus saya juga. Operasi pemicu adalah pelakunya.
autopilot
19

Dalam salah satu INSERTpernyataan, Anda mencoba memasukkan string yang terlalu panjang ke dalam string ( varcharataunvarchar kolom ).

Jika tidak jelas yang INSERTmerupakan pelaku hanya dengan melihat skrip, Anda dapat menghitung <1 row affected>garis yang terjadi sebelum pesan kesalahan. Angka yang diperoleh ditambah satu memberi Anda nomor pernyataan. Dalam kasus Anda tampaknya INSERT kedua yang menghasilkan kesalahan.

Andriy M
sumber
2
Saya mengalami masalah yang sama, bagaimana menemukan kolom mana yang menyebabkan kesalahan?
Cátia Matos
@ AndréBastos: Mungkin Anda bisa mengirimkannya sebagai pertanyaan (kecuali orang lain sudah melakukannya, dalam hal ini mungkin ada jawaban yang siap untuk itu di suatu tempat).
Andriy M
11

Beberapa data Anda tidak dapat masuk ke kolom basis data Anda (kecil). Tidak mudah menemukan apa yang salah. Jika Anda menggunakan C # dan Linq2Sql, Anda bisa mencantumkan bidang yang akan terpotong:

Pertama-tama buat kelas pembantu:

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);
                    }

                }
            }
        }
    }
}

Kemudian siapkan pembungkus untuk SubmitChanges:

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;
        }
    }
}

Mempersiapkan detail penangan pengecualian global dan pemotongan log:

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

Akhirnya gunakan kode:

Datamodel.SubmitChangesWithDetailException();
Tomas Kubes
sumber
9

Hanya ingin berkontribusi dengan informasi tambahan: Saya memiliki masalah yang sama dan itu karena bidangnya tidak cukup besar untuk data yang masuk dan utas ini membantu saya untuk menyelesaikannya (jawaban teratas menjelaskan semuanya).

TETAPI sangat penting untuk mengetahui apa alasan yang mungkin menyebabkannya.

Dalam kasus saya, saya membuat tabel dengan bidang seperti ini:

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

Oleh karena itu bidang "Periode" memiliki panjang Nol dan menyebabkan operasi Sisipan gagal. Saya mengubahnya menjadi "XXXXXX" yang merupakan panjang data yang masuk dan sekarang berfungsi dengan benar (karena bidang sekarang memiliki lentgh 6).

Saya harap ini membantu siapa pun dengan masalah yang sama :)

RaRdEvA
sumber
7

Situasi lain di mana Anda bisa mendapatkan kesalahan ini adalah sebagai berikut:

Saya memiliki kesalahan yang sama dan alasannya adalah bahwa dalam pernyataan INSERT yang menerima data dari UNION, urutan kolom berbeda dari tabel asli. Jika Anda mengubah urutan # table3 menjadi a, b, c, Anda akan memperbaiki kesalahan tersebut.

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

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

pada server sql Anda dapat menggunakan SET ANSI_WARNINGS OFF seperti ini:

        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();

        }
Esperento57
sumber
7

Saya memiliki masalah yang sama. The panjang kolom saya terlalu pendek.

Yang bisa Anda lakukan adalah menambah panjang atau memperpendek teks yang ingin Anda masukkan ke dalam basis data.

bizimunda
sumber
7

Juga memiliki masalah ini terjadi pada permukaan aplikasi web. Akhirnya menemukan bahwa pesan kesalahan yang sama berasal dari pernyataan pembaruan SQL di tabel tertentu.

Akhirnya kemudian menemukan bahwa definisi kolom dalam tabel sejarah terkait tidak memetakan panjang kolom nvarcharjenis tabel asli dalam beberapa kasus tertentu.

webMac
sumber
4

Saya memiliki masalah yang sama, bahkan setelah meningkatkan ukuran kolom bermasalah di tabel.

tl; dr: Panjang kolom yang cocok dalam Jenis Tabel yang sesuai mungkin juga perlu ditingkatkan.

Dalam kasus saya, kesalahan berasal dari layanan Ekspor Data di Microsoft Dynamics CRM, yang memungkinkan data CRM disinkronkan ke SQL Server DB atau Azure SQL DB.

Setelah penyelidikan panjang, saya menyimpulkan bahwa layanan Ekspor Data harus menggunakan Parameter Table-Valued :

Anda dapat menggunakan parameter bernilai tabel untuk mengirim beberapa baris data ke pernyataan Transact-SQL atau rutin, seperti prosedur atau fungsi tersimpan, tanpa membuat tabel sementara atau banyak parameter.

Seperti yang Anda lihat dalam dokumentasi di atas, Jenis Tabel digunakan untuk membuat prosedur konsumsi data:

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

Sayangnya, tidak ada cara untuk mengubah Jenis Tabel, sehingga harus dihapus & dibuat ulang seluruhnya. Karena tabel saya memiliki lebih dari 300 bidang (😱), saya membuat kueri untuk memfasilitasi pembuatan Jenis Tabel yang sesuai berdasarkan definisi kolom tabel (hanya ganti [table_name]dengan nama tabel Anda):

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;

Setelah memperbarui Jenis Tabel, layanan Ekspor Data mulai berfungsi dengan baik sekali lagi! :)

Marco Roy
sumber
2

Ketika saya mencoba menjalankan prosedur tersimpan saya, saya memiliki masalah yang sama karena ukuran kolom yang saya perlu tambahkan beberapa data lebih pendek daripada data yang ingin saya tambahkan.

Anda bisa menambah ukuran tipe data kolom atau mengurangi panjang data Anda.

Chamila Maddumage
sumber
1

Situasi lain, di mana kesalahan ini dapat terjadi adalah di SQL Server Management Studio. Jika Anda memiliki bidang "teks" atau "ntext" di tabel Anda, tidak peduli bidang apa yang sedang Anda perbarui (misalnya bit atau integer). Tampaknya Studio tidak memuat seluruh bidang "ntext" dan juga memperbarui SEMUA bidang alih-alih yang dimodifikasi. Untuk memecahkan masalah, kecualikan bidang "teks" atau "ntext" dari kueri di Management Studio

Sevast
sumber
1
Harap pertimbangkan untuk mengulangi jawaban Anda dengan menambahkan koma, titik, dan memperbaiki kesalahan tata bahasa Anda.
George Pamfilis
Jawaban ini membantu saya - bidang nvarchar saya cukup besar tetapi saya memiliki bidang ntext. Tampaknya ada beberapa kesalahan di Management Studio / SMSS.
Sha
0

Komentar Kevin Pope di bawah jawaban yang diterima adalah yang saya butuhkan.

Masalahnya, dalam kasus saya, adalah bahwa saya memiliki pemicu yang didefinisikan pada tabel saya yang akan memasukkan pembaruan / memasukkan transaksi ke dalam tabel audit, tetapi tabel audit memiliki ketidakcocokan tipe data di mana kolom dengan VARCHAR(MAX)dalam tabel asli disimpan seperti VARCHAR(1)dalam tabel audit, jadi pemicu saya gagal ketika saya akan memasukkan sesuatu yang lebih besar dari VARCHAR(1)pada kolom tabel asli dan saya akan mendapatkan pesan kesalahan ini.

Sibs
sumber
0

Saya menggunakan taktik yang berbeda, bidang yang dialokasikan 8K di beberapa tempat. Di sini hanya sekitar 50/100 yang digunakan.

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

Saya ingin kecepatan, karena saya memiliki catatan total 1M, dan memuat 28K dari mereka.

Hans Schulze
sumber