SQL 服务器更新并替换 "text" 和 "ntext" 字段中的垃圾邮件
SQL Server Update & Replace Spam in "text" and "ntext" fields
首先,感谢您抽出宝贵时间查看此问题。
旧数据库 table 中注入了超过 14k 个垃圾邮件链接,其中许多位于 text 和 ntext 字段中。我写了一个 SQL 查询,它运行和更新任何非 "text" 或 "ntext" 类型的字段,但不幸的是它不会更新 "text" 或 "ntext"字段。
关于数据库的简要信息:在IIS7上是运行,在Server 2008上是SQL,启用了PHP(版本5.3)。不幸的是,我直接或从控制面板更新数据库的能力非常有限(否则这会被迅速处理)所以我在 PHP 中编写这个脚本来自动更新受损的 tables。这种形式的脚本运行没有错误,但是我在 text 或 ntext 字段中没有任何更新。
脚本如下:
//Basic DB Connection
$conn = database_info;
$sql = "SELECT * FROM pages_test_only";
$result = sqlsrv_query($conn, $sql);
//Loop to scrub each table
foreach(sqlsrv_field_metadata($result) as $fieldMetadata)
{
//The loop here updates each section of spam (starting with </title>) with "" (empty/null)
//and leaves other content intact. The double quotes in the spam are escaped (\").
//Text update - if the field type is 'text'
if ($fieldMetadata['Type'] == -1)
{
$sqlupdate = "UPDATE pages_test_only SET ".$fieldMetadata['Name']." = CAST(REPLACE(CAST(".$fieldMetadata['Name']." as nvarchar(6000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', '') AS text";
}
//Ntext update - if the field type is 'ntext'
elseif ($fieldMetadata['Type'] == -10)
{
$sqlupdate = "UPDATE pages_test_only SET ".$fieldMetadata['Name']." = CAST(REPLACE(CAST(".$fieldMetadata['Name']." as nvarchar(6000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', '') AS ntext";
}
//Any other update - if the field contains the spam, but is of any other type [this is working]
else
{
$sqlupdate = "UPDATE pages_test_only SET ".$fieldMetadata['Name']." = REPLACE(".$fieldMetadata['Name'].", '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', '')";
}
//Send to DB
$res = sqlsrv_query($conn, $sqlupdate);
}
我知道将 text 和 ntext 字段永久转换为 nvarchar 是理想的,但是出于这些目的,我需要 table 结构在脚本完成时保持原样。
此外,如果您知道一种无需 SELECT SQL Server 2008 中的所有内容即可提取列元数据的方法,我将非常感谢此信息,因为它将加快我的查询速度实际 table.
请让我知道您看到了什么问题,再次感谢您的宝贵时间。
编辑:
虽然主要问题仍然存在,但我只能通过此查询提取字段名称和类型:
$sql = "SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.columns WHERE TABLE_NAME = 'pages_test_only'";
$result = sqlsrv_query($conn, $sql);
在while循环中应用:
while($row = sqlsrv_fetch_array($result)){
echo $row['COLUMN_NAME']."<br />";
echo $row['DATA_TYPE']."<br />";
//update - text type
if ($row['DATA_TYPE'] == 'text')
{
echo "This column is a text column.<br />";
$sqlupdate = "UPDATE pages_test_only SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(1000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', 'test') AS text";
}
//update - ntext type
elseif ($row['DATA_TYPE'] == 'ntext')
{
echo "This column is a ntext column.<br />";
$sqlupdate = "UPDATE pages_test_only SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(1000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', 'test') AS ntext";
}
//update - any other type
else
{
$sqlupdate = "UPDATE pages_test_only SET ".$row['COLUMN_NAME']." = REPLACE(".$row['COLUMN_NAME'].", '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', 'test')";
}
$res = sqlsrv_query($conn, $sqlupdate);
}
我有点尴尬,但我遇到的问题是语法。我忘记了每个 SQL 语句末尾的括号。话虽这么说,这里是
最终的工作更新集:
//basic connection information
$serverName = "dbhost.etc"; //serverName\instanceName
$connectionInfo = array( "Database"=>"db_name", "UID"=>"db_user", "PWD"=>"db_pass");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
//connection check
if( $conn )
{
echo "Connection established.<br /><br />";
}
else
{
echo "Connection could not be established.<br />";
die( print_r( sqlsrv_errors(), true));
}
//this selects ONLY the column name and type from the table
$sql = "SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.columns WHERE TABLE_NAME = 'table_name'";
$result = sqlsrv_query($conn, $sql);
//a loop is set up for each column that checks for data type and casts/updates accordingly
while($row = sqlsrv_fetch_array($result))
{
//update - text type
if ($row['DATA_TYPE'] == 'text')
{
$sqlupdate = "UPDATE table_name SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(max)), 'string', 'replacement') AS text)";
}
//update - ntext type
elseif ($row['DATA_TYPE'] == 'ntext')
{
$sqlupdate = "UPDATE table_name SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(max)), 'string', 'replacement') AS ntext)";
}
//update - any other type
else
{
$sqlupdate = "UPDATE table_name SET ".$row['COLUMN_NAME']." = REPLACE(".$row['COLUMN_NAME'].", 'string', 'replacement')";
}
$res = sqlsrv_query($conn, $sqlupdate);
}
首先,感谢您抽出宝贵时间查看此问题。
旧数据库 table 中注入了超过 14k 个垃圾邮件链接,其中许多位于 text 和 ntext 字段中。我写了一个 SQL 查询,它运行和更新任何非 "text" 或 "ntext" 类型的字段,但不幸的是它不会更新 "text" 或 "ntext"字段。
关于数据库的简要信息:在IIS7上是运行,在Server 2008上是SQL,启用了PHP(版本5.3)。不幸的是,我直接或从控制面板更新数据库的能力非常有限(否则这会被迅速处理)所以我在 PHP 中编写这个脚本来自动更新受损的 tables。这种形式的脚本运行没有错误,但是我在 text 或 ntext 字段中没有任何更新。
脚本如下:
//Basic DB Connection
$conn = database_info;
$sql = "SELECT * FROM pages_test_only";
$result = sqlsrv_query($conn, $sql);
//Loop to scrub each table
foreach(sqlsrv_field_metadata($result) as $fieldMetadata)
{
//The loop here updates each section of spam (starting with </title>) with "" (empty/null)
//and leaves other content intact. The double quotes in the spam are escaped (\").
//Text update - if the field type is 'text'
if ($fieldMetadata['Type'] == -1)
{
$sqlupdate = "UPDATE pages_test_only SET ".$fieldMetadata['Name']." = CAST(REPLACE(CAST(".$fieldMetadata['Name']." as nvarchar(6000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', '') AS text";
}
//Ntext update - if the field type is 'ntext'
elseif ($fieldMetadata['Type'] == -10)
{
$sqlupdate = "UPDATE pages_test_only SET ".$fieldMetadata['Name']." = CAST(REPLACE(CAST(".$fieldMetadata['Name']." as nvarchar(6000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', '') AS ntext";
}
//Any other update - if the field contains the spam, but is of any other type [this is working]
else
{
$sqlupdate = "UPDATE pages_test_only SET ".$fieldMetadata['Name']." = REPLACE(".$fieldMetadata['Name'].", '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', '')";
}
//Send to DB
$res = sqlsrv_query($conn, $sqlupdate);
}
我知道将 text 和 ntext 字段永久转换为 nvarchar 是理想的,但是出于这些目的,我需要 table 结构在脚本完成时保持原样。
此外,如果您知道一种无需 SELECT SQL Server 2008 中的所有内容即可提取列元数据的方法,我将非常感谢此信息,因为它将加快我的查询速度实际 table.
请让我知道您看到了什么问题,再次感谢您的宝贵时间。
编辑:
虽然主要问题仍然存在,但我只能通过此查询提取字段名称和类型:
$sql = "SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.columns WHERE TABLE_NAME = 'pages_test_only'";
$result = sqlsrv_query($conn, $sql);
在while循环中应用:
while($row = sqlsrv_fetch_array($result)){
echo $row['COLUMN_NAME']."<br />";
echo $row['DATA_TYPE']."<br />";
//update - text type
if ($row['DATA_TYPE'] == 'text')
{
echo "This column is a text column.<br />";
$sqlupdate = "UPDATE pages_test_only SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(1000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', 'test') AS text";
}
//update - ntext type
elseif ($row['DATA_TYPE'] == 'ntext')
{
echo "This column is a ntext column.<br />";
$sqlupdate = "UPDATE pages_test_only SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(1000)), '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', 'test') AS ntext";
}
//update - any other type
else
{
$sqlupdate = "UPDATE pages_test_only SET ".$row['COLUMN_NAME']." = REPLACE(".$row['COLUMN_NAME'].", '</title><div style=\"display:block; text-indent:-5670px;\"><a href=\"http://buy-cialis-onlineusa.com\">generic cialis</a></div>', 'test')";
}
$res = sqlsrv_query($conn, $sqlupdate);
}
我有点尴尬,但我遇到的问题是语法。我忘记了每个 SQL 语句末尾的括号。话虽这么说,这里是 最终的工作更新集:
//basic connection information
$serverName = "dbhost.etc"; //serverName\instanceName
$connectionInfo = array( "Database"=>"db_name", "UID"=>"db_user", "PWD"=>"db_pass");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
//connection check
if( $conn )
{
echo "Connection established.<br /><br />";
}
else
{
echo "Connection could not be established.<br />";
die( print_r( sqlsrv_errors(), true));
}
//this selects ONLY the column name and type from the table
$sql = "SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.columns WHERE TABLE_NAME = 'table_name'";
$result = sqlsrv_query($conn, $sql);
//a loop is set up for each column that checks for data type and casts/updates accordingly
while($row = sqlsrv_fetch_array($result))
{
//update - text type
if ($row['DATA_TYPE'] == 'text')
{
$sqlupdate = "UPDATE table_name SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(max)), 'string', 'replacement') AS text)";
}
//update - ntext type
elseif ($row['DATA_TYPE'] == 'ntext')
{
$sqlupdate = "UPDATE table_name SET ".$row['COLUMN_NAME']." = CAST(REPLACE(CAST(".$row['COLUMN_NAME']." as nvarchar(max)), 'string', 'replacement') AS ntext)";
}
//update - any other type
else
{
$sqlupdate = "UPDATE table_name SET ".$row['COLUMN_NAME']." = REPLACE(".$row['COLUMN_NAME'].", 'string', 'replacement')";
}
$res = sqlsrv_query($conn, $sqlupdate);
}