当 nvarchar(max) 的上限为 4000 个字符时,无法存储 HTML 页
cant store an HTML page when ncarchar(max) is capped at 4000 characters
简单来说,如何增加 nvarchar(MAX) 的上限以实际容纳 280MB 的文本而不仅仅是 8000MB(如果我错了请纠正我)?
因此,对于我的期末项目,我正在为希望为其图书馆网站使用自己的自定义搜索引擎的客户制作网络爬虫,但是当我尝试存储爬虫检索的信息时,我的问题就出现了。
我遇到的具体问题是,即使我将列 "HTML" 设置为 nvarchar(MAX),它应该能够容纳 2GB 的数据,但它不会向其中保存任何信息,在这种情况下280MB,因为它太长了。
我确实尝试缩短要保存的文本的长度,当我让它足够短时,它最终同意保存数据,所以据我所知它是有上限的。
编辑:请求的代码示例
页面容器class:
public class Page
{
public int ID = -1;
public String URL;
public String HeadLine;
public List<String> Tags;
public String Description;
public String HTML;
public DateTime lastUpdate;
}
爬虫保存它检索到的页面时的代码片段:
//Save Page content to Database
Page page = new Page();
page.URL = url;
page.HeadLine = headline;
page.Tags = tags.Split(',').Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
page.Description = description;
page.HTML = HTML;
page.lastUpdate = DateTime.Today;
new DBpage(Settings.instance.DBaddress,
Settings.instance.DBname).SavePage(page);
用于存储数据的方法:
public void SavePage(Page page) {
String SqlString = "";
//Check is a page by the given URL already exists in the database and assign the SQL string acordingly
Page foundPage = GetPage(page.URL);
if(foundPage == null) {
SqlString = "INSERT INTO WebContent " +
"VALUES (@URL, @HeadLine, @Tags, @Description, @HTML, @LastUpdate)";
}
else {
SqlString = "UPDATE WebContent " +
"SET URL = @URL, HeadLine = @HeadLine, Tags = @Tags, Description = @Description, HTML = @HTML, LastUpdate = @LastUpdate " +
//"SET URL = '" + page.URL + "', HeadLine = '" + page.HeadLine + "', Tags = '" + String.Join(",", page.Tags) + "', Description = '" + page.Description + "', HTML = '" + page.HTML.Replace("'", "''") + "', LastUpdate = " + page.lastUpdate + " " +
"WHERE ID = " + foundPage.ID;
}
//Assign all variables and execute the SQL
try {
using(DBaccess db = new DBaccess(dblocation, dbname)) {
String html = page.HTML.Replace("'", "''"); //Replace all single quotes with double "single quotes" to escape the first single quote.
SqlCommand sqlCmd = db.GetSqlCommand(SqlString);
sqlCmd.Parameters.AddWithValue("@URL", page.URL);
sqlCmd.Parameters.AddWithValue("@HeadLine", page.HeadLine);
sqlCmd.Parameters.AddWithValue("@Tags", String.Join(",", page.Tags));
sqlCmd.Parameters.AddWithValue("@Description", page.Description);
sqlCmd.Parameters.AddWithValue("@HTML", html);
sqlCmd.Parameters.AddWithValue("@LastUpdate", page.lastUpdate);
sqlCmd.ExecuteNonQuery();
}
}
catch(SqlException e) {
Console.WriteLine(e.Message);
}
}
令我困惑的不幸结果:
nvarchar(max)
类型允许存储最多 2GB 的数据。对于 nvarchar,它意味着大约 10 亿个字符,因为 N
类型以每个字符 unicode 2 字节存储文本。
nvarchar [ ( n | max ) ]
Variable-length Unicode string data. n defines the string length
and can be a value from 1 through 4,000. max indicates that the
maximum storage size is 2^30-1 characters. The maximum storage size in
bytes is 2 GB. The actual storage size, in bytes, is two times the
number of characters entered + 2 bytes.
很可能您的问题出在尝试插入如此大文本的过程中。首先想到的是一些超时。将 280MB 的数据上传到服务器需要一段时间,因此请检查失败的详细信息(查看错误消息和异常)以收集出错的线索。
需要检查的几件事:
仔细检查数据库中 HTML
列的类型。
可能 SSMS 没有正确显示 long 值。尝试 运行
SELECT LEN(HTML) FROM YourTable
验证存储字符串的长度。
总的来说,只需在调试器中逐步执行代码并验证所有变量是否具有预期值。
简单来说,如何增加 nvarchar(MAX) 的上限以实际容纳 280MB 的文本而不仅仅是 8000MB(如果我错了请纠正我)?
因此,对于我的期末项目,我正在为希望为其图书馆网站使用自己的自定义搜索引擎的客户制作网络爬虫,但是当我尝试存储爬虫检索的信息时,我的问题就出现了。
我遇到的具体问题是,即使我将列 "HTML" 设置为 nvarchar(MAX),它应该能够容纳 2GB 的数据,但它不会向其中保存任何信息,在这种情况下280MB,因为它太长了。
我确实尝试缩短要保存的文本的长度,当我让它足够短时,它最终同意保存数据,所以据我所知它是有上限的。
编辑:请求的代码示例
页面容器class:
public class Page
{
public int ID = -1;
public String URL;
public String HeadLine;
public List<String> Tags;
public String Description;
public String HTML;
public DateTime lastUpdate;
}
爬虫保存它检索到的页面时的代码片段:
//Save Page content to Database
Page page = new Page();
page.URL = url;
page.HeadLine = headline;
page.Tags = tags.Split(',').Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
page.Description = description;
page.HTML = HTML;
page.lastUpdate = DateTime.Today;
new DBpage(Settings.instance.DBaddress,
Settings.instance.DBname).SavePage(page);
用于存储数据的方法:
public void SavePage(Page page) {
String SqlString = "";
//Check is a page by the given URL already exists in the database and assign the SQL string acordingly
Page foundPage = GetPage(page.URL);
if(foundPage == null) {
SqlString = "INSERT INTO WebContent " +
"VALUES (@URL, @HeadLine, @Tags, @Description, @HTML, @LastUpdate)";
}
else {
SqlString = "UPDATE WebContent " +
"SET URL = @URL, HeadLine = @HeadLine, Tags = @Tags, Description = @Description, HTML = @HTML, LastUpdate = @LastUpdate " +
//"SET URL = '" + page.URL + "', HeadLine = '" + page.HeadLine + "', Tags = '" + String.Join(",", page.Tags) + "', Description = '" + page.Description + "', HTML = '" + page.HTML.Replace("'", "''") + "', LastUpdate = " + page.lastUpdate + " " +
"WHERE ID = " + foundPage.ID;
}
//Assign all variables and execute the SQL
try {
using(DBaccess db = new DBaccess(dblocation, dbname)) {
String html = page.HTML.Replace("'", "''"); //Replace all single quotes with double "single quotes" to escape the first single quote.
SqlCommand sqlCmd = db.GetSqlCommand(SqlString);
sqlCmd.Parameters.AddWithValue("@URL", page.URL);
sqlCmd.Parameters.AddWithValue("@HeadLine", page.HeadLine);
sqlCmd.Parameters.AddWithValue("@Tags", String.Join(",", page.Tags));
sqlCmd.Parameters.AddWithValue("@Description", page.Description);
sqlCmd.Parameters.AddWithValue("@HTML", html);
sqlCmd.Parameters.AddWithValue("@LastUpdate", page.lastUpdate);
sqlCmd.ExecuteNonQuery();
}
}
catch(SqlException e) {
Console.WriteLine(e.Message);
}
}
令我困惑的不幸结果:
nvarchar(max)
类型允许存储最多 2GB 的数据。对于 nvarchar,它意味着大约 10 亿个字符,因为 N
类型以每个字符 unicode 2 字节存储文本。
nvarchar [ ( n | max ) ]
Variable-length Unicode string data. n defines the string length and can be a value from 1 through 4,000. max indicates that the maximum storage size is 2^30-1 characters. The maximum storage size in bytes is 2 GB. The actual storage size, in bytes, is two times the number of characters entered + 2 bytes.
很可能您的问题出在尝试插入如此大文本的过程中。首先想到的是一些超时。将 280MB 的数据上传到服务器需要一段时间,因此请检查失败的详细信息(查看错误消息和异常)以收集出错的线索。
需要检查的几件事:
仔细检查数据库中 HTML
列的类型。
可能 SSMS 没有正确显示 long 值。尝试 运行
SELECT LEN(HTML) FROM YourTable
验证存储字符串的长度。
总的来说,只需在调试器中逐步执行代码并验证所有变量是否具有预期值。