错误,string或二进制数据在尝试插入时会被截断
我使用以下几行运行data.bat文件:
Rem Tis batch file will populate tables cd\program files\Microsoft SQL Server\MSSQL osql -U sa -P Password -d MyBusiness -ic:\data.sql
data.sql文件的内容是:
insert Customers (CustomerID, CompanyName, Phone) Values('101','Southwinds','19126602729')
有8个更多的类似的行添加logging。
当我运行此与start
> run
> cmd
> c:\data.bat
,我得到这个错误信息:
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>
另外,我明显是一个新手,但是Level #
和state #
是什么意思呢,我怎么看上面的错误信息:8152?
提前致谢!
从@ gmmastros的答案
每当你看到消息….
string or binary data would be truncated
想想自己……这个领域还不够大,无法保存我的数据。
检查客户表的表结构。 我想你会发现一个或多个字段的长度不足以容纳你试图插入的数据。 例如,如果Phone字段是一个varchar(8)字段,并且您尝试将11个字符input到该字段中,则会出现此错误。
在其中一个INSERT
语句中,您试图将太长的string插入到string( varchar
或nvarchar
)列中。
如果仅仅通过查看脚本就不清楚哪一个INSERT
是违规者,则可以计数错误消息之前发生的<1 row affected>
行。 所获得的数字加1就是你的语句编号。 在你的情况下,似乎是产生错误的第二个INSERT。
我有这个问题,虽然数据长度比字段长度短。 事实certificate,问题是另一个日志表(用于审计跟踪),由主表上的触发器填充,其中列大小也必须改变。
有些数据无法放入数据库列(小)。 find错误并不容易。 如果您使用C#和Linq2Sql,您可以列出将被截断的字段:
首先创build助手类:
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); } } } } } }
然后准备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; } } }
准备全局exception处理程序和日志截断详细信息:
protected void Application_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); string message = ex.Message; //TODO - log to file }
最后使用代码:
Datamodel.SubmitChangesWithDetailException();
也有这个问题发生在Web应用程序的表面上。 最终发现相同的错误消息来自特定表中的SQL更新语句。
最后,我们发现在一些特定情况下,相关历史表中的列定义没有映射nvarchar
types的原始表列长度。
希望这个提示可以帮助别人..;)
只是想提供额外的信息:我有同样的问题,这是因为该领域是不够大的传入数据,这促使我解决它(最好的答案澄清了这一切)。
但是知道可能导致什么原因是非常重要的。
在我的情况下,我正在创build一个像这样的字段的表:
Select '' as Period, * From Transactions Into #NewTable
因此,“期间”字段的长度为零,导致插入操作失败。 我将它改为“XXXXXX”,即传入数据的长度,现在它正常工作(因为字段现在有6个字节)。
我希望这可以帮助任何人有同样的问题:)
在sql server上,你可以像这样使用SET ANSI_WARNINGS OFF:
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(); }
你可以得到这个错误的另一种情况如下:
我有同样的错误,原因是在从UNION接收数据的INSERT语句中,列的顺序与原始表的顺序不同。 如果您将#table3中的顺序更改为a,b,c,则将修复错误。
select a, b, c into #table1 from #table0 insert into #table1 select a, b, c from #table2 union select a, c, b from #table3
我遇到过同样的问题。 我的专栏太短了。 你可以做的是增加长度或缩短你想放在数据库中的文字。