对sqlite已有数据,添加多列的唯一性约束

以一个数据表为例, 创建sql如下:

CREATE TABLE http_table (
    id       INTEGER PRIMARY KEY AUTOINCREMENT,
    Host     TEXT    DEFAULT "",
    IP       TEXT    DEFAULT "",
    Port     INTEGER DEFAULT (0),
    Info     TEXT    DEFAULT "",
    Uptime   TEXT    DEFAULT (datetime('now', 'localtime') ) 
);

当前该表已有不少数据存在,只有id为自增长主键,未创建约束。

之前创建数据过程,先查询(1),不存在新插入一条(2),存在更新该条记录(3):

(1)先查询

SELECT id FROM http_table WHERE Host = 'dns9.quad9.net' AND IP = '9.9.9.9' AND Port = '80' order by Uptime desc LIMIT 1;

(这里,可能是多条,只返回一条)

(2)不存在新插入一条

INSERT INTO http_table (Host, IP, Port, Info) VALUES ('dns9.quad9.net', '9.9.9.9', '80', 'new_info');

(3)存在更新该条记录

UPDATE http_table SET Info = 'new_info' WHERE Host = 'dns9.quad9.net' AND IP = '9.9.9.9' AND Port = '80';

本身这个更新并不严谨,没有指定唯一id条件,可能会更新多条,但这不是要解决的问题。

问题在于在大批量的数据插入时,每次都要查询,再判断是插入还更新,速度很慢,现需要一条sql一次完成查询,并完成插入或更新。

尝试修改:在 SQLite 中,可以使用 INSERT INTO...ON CONFLICT 子句配合 DO UPDATE 动作,实现根据特定条件存在则更新记录,不存在则插入新记录的功能。

INSERT INTO http_table (Host, IP, Port, Info)
VALUES ('dns9.quad9.net', '9.9.9.9', '80', 'new_info')
ON CONFLICT(Host, IP, Port) DO UPDATE SET
    Info=excluded.Info;
解释:

INSERT INTO http_table (Host, IP, Port, Info) VALUES (...) 尝试插入一条新记录。


ON CONFLICT(Host, IP, Port) 指定当 Host, IP, Port 这三个字段的组合发生冲突时(即已存在这样的记录时)应采取的动作。


DO UPDATE SET Info=excluded.Info 指定当冲突发生时,更新已有记录的 Info 字段。excluded 是一个特殊的表别名,它引用尝试插入但因冲突而未能插入的值。


这样,如果记录已存在,Info 字段将被更新为新的值;如果记录不存在,则将插入新的记录

首先,你需要确保你的表有一个唯一约束(UNIQUE CONSTRAINT)来检测冲突。在这个例子中,需要设定 HostIP, 和 Port 的组合是唯一的,UNIQUE(Host, IP, Port)否则会报错。

CREATE TABLE http_table(
    Host TEXT,
    IP TEXT,
    Port TEXT,
    Info TEXT,
    UNIQUE(Host, IP, Port)
);

由于之前未添加唯一约束,执行INSERT INTO http_table ... ON CONFLICT(Host, IP, Port) DO UPDATE ... 会如下报错:

执行 SQL 查询时发生错误:ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint

解决方法建立约束前,清洗现有数据

在建立唯一性约束之前,如果现有数据中存在违反该约束的重复记录,你需要进行数据清洗。数据清洗的过程通常包括识别重复记录、决定如何处理这些记录(如删除、合并或修改),以及执行相应的操作。以下是一些步骤和建议,帮助你清洗现有数据以便能够添加唯一性约束:

识别重复记录

使用SQL查询来找出在HostIPPort列上有重复组合的记录。可以使用GROUP BYHAVING子句来识别这些重复项。以下查询将找出所有重复的HostIPPort组合以及它们出现的次数:

SELECT Host, IP, Port, COUNT(*) as count FROM http_table GROUP BY Host, IP, Port HAVING COUNT(*) > 1;

决定如何处理重复记录

  • 删除重复项:如果重复记录没有保留价值,你可以选择删除它们。确保在删除之前备份数据,以防万一。
  • 合并记录:如果重复记录包含有用的信息,你可能想要合并它们。这通常涉及更新一条记录以包含所有相关信息,并删除其他重复记录。
  • 修改记录:在某些情况下,你可能能够通过修改重复记录中的一个或多个字段来消除重复。

执行数据清洗操作

根据你的决定,编写SQL语句来执行删除、合并或修改操作。

如果你决定删除重复的记录,并且只保留每个组合的第一条记录,你可以使用以下查询(请注意,这个查询假设你有一个唯一标识每条记录的id字段):

DELETE FROM http_table WHERE id NOT IN ( SELECT MIN(id) FROM http_table GROUP BY Host, IP, Port );

这个查询会删除每个HostIPPort组合中除id最小的一条记录之外的所有记录。

验证数据清洗结果

在执行数据清洗操作后,再次运行识别重复记录的查询,确保所有重复项都已被处理。

检查数据以确保没有其他问题,如数据丢失或不一致。

添加唯一性约束

确认数据已经清洗干净,没有违反唯一性约束的重复记录,可以安全地添加唯一性约束了。使用ALTER TABLE语句来添加约束:

ALTER TABLE http_table 
ADD CONSTRAINT unique_host_ip_port UNIQUE(Host, IP, Port);

这时又发生错误!

执行 SQL 查询时发生错误:near "CONSTRAINT": syntax error

在SQLite中,ALTER TABLE 语句用于修改表的结构,比如添加列、重命名表、添加约束等。但是,SQLite 在使用 ALTER TABLE 添加约束时有一些限制,特别是关于唯一性约束(UNIQUE CONSTRAINT)。

在SQLite中,如果你想要给一个已经存在的表添加一个新的唯一性约束,并且这个约束涉及到多个列,你不能直接在 ALTER TABLE 语句中使用 ADD CONSTRAINT 语法。SQLite不支持这种直接添加多列唯一性约束的方式。

相反,你需要采取一种间接的方法来实现这一点。以下是一种可能的解决方案:

  1. 创建一个新表:这个新表应该包含与原始表相同的列,并且包含你想要添加的唯一性约束。
  2. 复制数据:将原始表中的数据复制到新表中,同时确保没有违反唯一性约束的数据被插入。
  3. 删除原始表(可选):如果数据复制成功,并且你确定新表包含了所有需要的数据,你可以删除原始表。
  4. 重命名新表:将新表重命名为原始表的名称。

务必注意:备份数据

在进行任何数据修改或结构更改之前,始终确保你有最新的数据备份。这是防止数据丢失或损坏的重要步骤。

请记住,数据清洗是一个可能对数据产生重大影响的操作。在执行任何删除或修改操作之前,务必仔细考虑并备份你的数据。

最终执行的SQL语句是:

--修改原更新语句,使用 INSERT INTO ... ON CONFLICT ... DO UPDATE 方式,一次查询执行插入或删除。

INSERT INTO http_table (Host, IP, Port, Title, Url, Info, Location, Method, Code, Tag, Server) 
VALUES ('Host', 'IP', 'Port', 'Title', 'Url', 'Info', 'Location', 'Method', 'Code', 'Tag', 'Server') 
ON CONFLICT (Host, IP, Port) DO UPDATE SET Info = excluded.Info;

-- 添加唯一约束,操作步骤:

-- 首先备份原始的 .db 文件

-- 识别重复记录
SELECT Host, IP, Port, COUNT( * ) AS count
  FROM http_table
 GROUP BY Host, IP, Port
HAVING COUNT( * ) > 1;

-- 删除重复记录
DELETE FROM http_table
      WHERE id NOT IN (
    SELECT MIN(id) 
      FROM http_table
     GROUP BY Host, IP, Port
);

-- 创建包含唯一性约束的新表
CREATE TABLE new_http_table (
    id       INTEGER PRIMARY KEY AUTOINCREMENT,
    Host     TEXT    DEFAULT "",
    IP       TEXT    DEFAULT "",
    Port     INTEGER DEFAULT (0),
    Title    TEXT    DEFAULT "",
    Url      TEXT    DEFAULT "",
    Info     TEXT    DEFAULT "",
    Location TEXT    DEFAULT "",
    Method   TEXT    DEFAULT "",
    Code     INTEGER DEFAULT "",
    Tag      TEXT    DEFAULT "",
    Server   TEXT    DEFAULT "",
    Uptime   TEXT    DEFAULT (datetime('now', 'localtime') ) ,
    UNIQUE(Host, IP, Port)
);

-- 复制数据到新表(确保没有重复项)
INSERT INTO new_http_table (id, Host, IP, Port, Title, Url, Info, Location, Method, Code, Tag, Server, Uptime)
	SELECT id, Host, IP, Port, Title, Url, Info, Location, Method, '', Tag, Server, Uptime
	FROM http_table
	WHERE (Host, IP, Port) IN (SELECT Host, IP, Port
								FROM http_table
								GROUP BY Host, IP, Port
								HAVING COUNT( * ) = 1);

-- 查询对比新旧两个表数据总数
SELECT (SELECT COUNT( * ) 
          FROM http_table) AS old_count, (SELECT COUNT( * ) 
                                                    FROM new_http_table) AS new_count;

-- (可选)删除原始表
--DROP TABLE http_table;

-- 重命名原始表的名称
ALTER TABLE http_table RENAME TO back_http_table;

-- 重命名新表为原始表的名称
ALTER TABLE new_http_table RENAME TO http_table;

-- (可选)删除备份表
--DROP TABLE back_http_table;

--释放空闲占用(类似收缩数据库)
VACUUM;

--检查数据库完整性
PRAGMA integrity_check;

--数据处理全部完成

sqlite 简单手记

delete from TableName;  //清空数据 
update sqlite_sequence SET seq = 0 where name ='TableName';//自增长ID为0
更新删除时,如何插入有单引号(')的字符串,将所有单引号替换为两个单引号

sql = sql.Replace("'","''");

保存到SQLite数据库中时自动恢复为单引号,也就是说使用双单引号即可,例如:
INSERT INTO TableName VALUES('James''s Street');
插入数据库的是: James's Street 。

sqlite数据库在搜索的时候,一些特殊的字符需要进行转义, 具体的转义如下: 
     /   ->    //
     ‘   ->    ”
     [   ->    /[
     ]   ->    /]
     %   ->    /%
     &   ->    /&
        ->    /
     (   ->    /(
     )   ->    /)

IP地址在mysql的存储(IP地址和int的转换)

文章作者:Enjoy 转载请注明原文链接。

PHP
echo ip2long(‘192.168.1.38’);
输出:3232235814

MYSQL
SELECT INET_ATON(‘192.168.1.38’);
输出:3232235814

两个函数返回的结果是一样的,都是A*256*256*256+B*256*256+C*256+D的算法
192*256*256*256+168*256*256+1*256+38 = 3 232 235 814

反过来,从int转换为IP地址分别是php的long2ip()和mysql的INET_NTOA()。

mysql存储这个值是字段需要用int UNSIGNED。不用UNSIGNED的话,128以上的IP段就存储不了了。

传统的方法,创建varchar(15),需要占用15个字节,而改时使用int只需要4字节,可以省一些字节。

php存入时:$ip = ip2long($ip);
mysql取出时:SELECT INET_ATON(ip) FROM table …
php取出时,多一步:$ip = long2ip($ip);

转换以前的数据:

1.把以前的varchar()数据转换为int型的SQL语句:
UPDATE `hx_table` SET ip =  INET_ATON(ip) WHERE INET_ATON(ip) is NOT NULL
2.把字段更改为int型:
ALTER TABLE `hx_table` CHANGE `ip` `ip` INT UNSIGNED NOT NULL
3.程序做相应修改上传,完成。

@@UPDATE@@20110310:

在32位的机子上,echo ip2long(‘192.168.1.38’);由于超过32位的最大数,导致输出负数-1062731482。

有两种方法更新为正数:
$ip_long = bindec(decbin(ip2long($ip)));

$ip_long = = sprintf(“%u”, ip2long($ip));
因此一种是修改PHP程序,使其肯定存入正数。
另一种是将mysql的这个字段使用int,非UNSIGNED,使其可以存入负数。

MS SQL SERVER 数据字典 生成SQL

在库内查询,可用于生成如下字段结构:

[表], [字段], [数据类型], [允许为空], [主键], [外键], [引用表], [说明描述]

SELECT TOP (100) PERCENT a.name AS 表, b.name AS 字段, c.name AS 数据类型, CASE WHEN b.isnullable = 0 THEN '-' WHEN b.isnullable = 1 THEN '是' END AS 允许为空,
CASE WHEN d .name IS NULL THEN '-' WHEN d .name IS NOT NULL THEN '是' END AS 主键, CASE WHEN e.parent_object_id IS NULL THEN 0 ELSE 1 END AS 外键,
CASE WHEN e.parent_object_id IS NULL THEN '-' ELSE g.name END AS 引用表, CASE WHEN h.value IS NULL THEN '-' ELSE h.value END AS 说明描述,
i.text AS 默认值
FROM sys.sysobjects AS a INNER JOIN
sys.syscolumns AS b ON a.id = b.id INNER JOIN
sys.systypes AS c ON b.xtype = c.xtype LEFT OUTER JOIN
(SELECT so.id, sc.colid, sc.name
FROM sys.syscolumns AS sc INNER JOIN
sys.sysobjects AS so ON so.id = sc.id INNER JOIN
sys.sysindexkeys AS si ON so.id = si.id AND sc.colid = si.colid
WHERE (si.indid = 1)) AS d ON a.id = d.id AND b.colid = d.colid LEFT OUTER JOIN
sys.foreign_key_columns AS e ON a.id = e.parent_object_id AND b.colid = e.parent_column_id LEFT OUTER JOIN
sys.objects AS g ON e.referenced_object_id = g.object_id LEFT OUTER JOIN
sys.extended_properties AS h ON a.id = h.major_id AND b.colid = h.minor_id LEFT OUTER JOIN
sys.syscomments AS i ON b.cdefault = i.id
WHERE (a.type = 'U') AND (c.name <> 'sysname')
ORDER BY 表, 字段

还有一个查全库表字段的,参见另一篇 《通过(sys.sysobjects)对象表,查询全库表的基础信息Sql Server 查询全库表信息

MySql中表名使用双下划线”__”,phpMyAdmin中将以前缀分组显示

很久没有更新过新版的phpMyAdmin了,前些天装了个版本: 4.0.10.9,提示最新版本已经是: 4.4.4.

启用 phpMyAdmin 高级功能,导入 create_tables.sql 时,难得细心看了下sql,发现里面的表名都是两个“__”下划线,以前是一个的,如下:

  • `pma__history`
  • `pma__pdf_pages`
  • `pma__######`

导入后在phpMyAdmin中发现,数据库中“pma”开头的表可以分组收缩。(如同)

20150501223253

忽然明白,表面中的双下划线“__”就是让MySql数据库内的表名进行分组的依据, “__ ”之前的字符标志就是分组名称。

于是把自己有些乱的库中表名也进行了前缀分组。

P.S. 不知道这个双下划线”__”前缀分组的功能是MySql的原生的功能,还是phpMyAdmin自定义的,我想应该是phpMyAdmin自己定义功能。

VPS下对mysql内存性能的优化

VPS的内存对性能至关重要,所以很有必要优化一下。

看了几篇针对vps小内存优化的文章,于是自己也动手参照优化下自己的mysql。

修改过调整好的 my.cnf ,service mysqld restart 启动时报错。

查看log,发现 skip-innodb / skip-bdb / skip-locking,这几个参数有问题。

 

继续学习,查资料,得知 使用的参数都是老版本的参数,mysql5.1对应的为:

skip-innodb  –>  loose-skip-innodb

skip-locking  –> skip-external-locking

skip-bdb (已经废除了skip-bdb这个参数!)

 

配置文件: /etc/my.cnf

# low memory stuff – Mr.Tang
# Tue May 26 22:23:15 CST 2015

[mysqld]

loose-skip-innodb
skip-external-locking
skip-host-cache
skip-name-resolve

character_set_server = utf8
default-storage-engine = myisam

key_buffer_size = 256M
key_buffer = 256K
max_allowed_packet = 1M
myisam_sort_buffer_size = 8M
net_buffer_length = 128K
query_cache_size= 16M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
sort_buffer_size = 1M
table_cache = 4M
table_open_cache = 16M
thread_cache_size = 8M
thread_stack = 131072

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash
#safe-updates

[isamchk]
key_buffer = 8M
sort_buffer_size = 8M

[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

SQL 增加自动增长id列

方法1:

在表设计器中手动创建列,选择标识,种子,增量。

方法2:

直接建表是创建生成

CREATE TABLE Tab_Test (ID int IDENTITY (1, 1), Name varchar(50))

方法3:

修改以有的表,增加一列

ALTER TABLE _TAB_Epm_Users ADD nID int IDENTITY (1, 1)

方法4:

用存储过程完成, 我没用过。自己查下。

方法5:

其他方法, 也可以变通完成。

比如:在插入数据时可以 先 MAX(nID)  原主键,然后+1后插入。

比如:已有一张表,我想在表里增加一个自动增长列,但是我想添进去的自动增长列按关键字order by排序,有简单易行的方法吗

——解决方案——————–
select NewID = identity(int,1,1), * into NewTable from OldTable order by 旧的数据的编号按关键字排序
——解决方案——————–
用2005的排序函数 row_number()
select row_number() over (order by id), * from sysobjects

些许会常用到的sql语句

这里记录些许个会经常用到的sql语句。

 

P.S.   [Your_Table]  = 你的表名, [nid] = 你表中的主键唯一列.

/*按分页数量取表记录中的数据*/
/*以nid排序, 取20条之后的10条*/SELECT TOP 10 *
FROM Your_Table
WHERE (nid NOT IN
          (SELECT TOP 20 nid
         FROM Your_Table
         ORDER BY nid))
ORDER BY nid
/*取传入条件记录的前一条数据*/
/*取 nid='533' 记录的前一条, 返回记录 nid='532'*/
SELECT *
FROM Your_Table
WHERE (nid =
          (SELECT MAX(nid)
         FROM Your_Table
         WHERE nid < 533))
/*取传入条件记录的后一条数据*/
/*取 nid='533' 记录的后一条, 返回记录 nid='532'*/		 
SELECT *
FROM Your_Table
WHERE (nid =
          (SELECT MIN(nid)
         FROM Your_Table
         WHERE nid > 534))
		 
		 

 

分页存储过程,SQL 2000 数据库下使用的:

-- =============================================

-- DocumentName       分页存储过程 SQL 2000数据库下使用的

-- 描述               利用SQL查询语句进行分页

-- 输入

--       {

--        @SQL            :    SQL查询语句,示例:'Select * from [TableName]'

--        @Order        :    排序,示例:[ColumnName] [ASC | DESC]

--        @CurPage        :    当前页,示例:0..9

--        @PageRows        :    每页显示的行数,示例:0..9

--        @TotalRecorder:    查询记录总数(输出参数)

--          @IsXML        :    表示返回的结果,0表示以表格形式记录,1表示以XML格式返回记录;默认为0

--       }

-- =============================================



ALTER PROCEDURE [dbo].[SeparatePage]

    -- Add the parameters for the stored procedure here

    @SQL Nvarchar(2000),

    @Order Nvarchar(20),

    @CurPage int,

    @PageRows int,

    @TotalRecorder int output,

    @IsXML bit = 0

AS

BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from

    SET NOCOUNT ON;

    declare @ExceSQL nvarchar(4000)

    

    --设置开始行号

    declare  @start_row_num AS int

    SET @start_row_num = (@CurPage - 1) * @PageRows

   

    if @CurPage > 1 

        BEGIN

            SET @start_row_num = @start_row_num + 1;

            SET @PageRows = @PageRows - 1

        END

    else

        SET @start_row_num = @start_row_num

    

    --获取总记录数

    set @ExceSQL = 'SELECT tb.* into [tb_Temp] FROM ('+ @SQL +') tb ORDER BY'+ @order

    execute(@ExceSQL)

    SELECT @TotalRecorder = COUNT(*) from [tb_Temp]



    ALTER TABLE [tb_Temp] add [RowNumber] int



    --设置查询语句

    SET @ExceSQL = 'SELECT TOP '+ convert(varchar(10),@PageRows) +' * 

                    FROM (SELECT TOP '+ convert(varchar(10),@PageRows) +' * 

                    FROM (SELECT TOP '+ convert(varchar(10),@TotalRecorder-@start_row_num+1) +' *

                    FROM [tb_Temp] ORDER BY '+ REPLACE(@Order,'DESC','ASC') +') AS a

                    ORDER BY '+ REPLACE(@Order,'ASC','DESC') +') AS b'



    IF(@IsXML = 1)

        SET @ExceSQL = @ExceSQL + ' FOR XML AUTO,ELEMENTS'

 

    EXECUTE(@ExceSQL)

    DROP Table [tb_Temp]

END

 

分页存储过程,SQL 2005 数据库下使用的:

set ANSI_NULLS ON

set QUOTED_IDENTIFIER ON

go


-- =============================================

-- DocumentName       分页存储过程  SQL 2005数据库下使用

-- 描述                 利用SQL查询语句进行分页

-- 输入

--       {

--        @SQL            :    SQL查询语句,示例:'Select * from [TableName]'

--        @Order        :    排序,示例:[ColumnName] [ASC | DESC]

--        @CurPage        :    当前页,示例:0..9

--        @PageRows        :    每页显示的行数,示例:0..9

--        @TotalRecorder:    查询记录总数(输出参数)

--          @IsXML        :    表示返回的结果,0表示以表格形式记录,1表示以XML格式返回记录;默认为0

--       }

-- =============================================



ALTER PROCEDURE [dbo].[SeparatePage]

    -- Add the parameters for the stored procedure here

    @SQL Nvarchar(2000),

    @Order Nvarchar(20),

    @CurPage int,

    @PageRows int,

    @TotalRecorder int output,

    @IsXML bit = 0

AS

BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from

    SET NOCOUNT ON;

    declare @ExceSQL nvarchar(4000)

    

    --设置开始行号

    declare  @start_row_num AS int

    SET @start_row_num = (@CurPage - 1) * @PageRows

   

    if @CurPage > 1 

        BEGIN

            SET @start_row_num = @start_row_num + 1;

            SET @PageRows = @PageRows - 1

        END

    else

        SET @start_row_num = @start_row_num

    

    --设置标签语句

    declare @RowNumber nvarchar(100)

    set @RowNumber = ', ROW_NUMBER() OVER(ORDER BY ' + @Order + ') as RowNumber from '



    set @SQL = Replace(@SQL,' from ',@RowNumber)



    --获取总记录数

    set @ExceSQL = 'WITH [TempTable] AS (' + @SQL + ') 

        select @TotalRecorder=max(RowNumber) from [TempTable]'



    execute sp_executesql @ExceSQL,N'@TotalRecorder int output',@TotalRecorder output



    --设置查询语句

    set @ExceSQL = 'WITH [TempTable] AS (' + @SQL + ') 

        select * from [TempTable] where RowNumber between ' + Convert(nvarchar,@start_row_num)

        + ' And ' + Convert(nvarchar,@start_row_num+@PageRows)

    

    IF(@IsXML = 1)SET @ExceSQL = @ExceSQL + 'FOR XML AUTO,ELEMENTS'

 

    execute(@ExceSQL)



END

 

查询获取表中, 字段,数据类型的sql

存档一个今天用到的sql,  可以用来查询表中, 字段, 数据类型的sql.

SELECT OBJECT_NAME(c.id) AS 表名, c.name AS 字段名, t.name AS 数据类型, 
      c.prec AS 长度
FROM syscolumns c INNER JOIN
      systypes t ON c.xusertype = t.xusertype
WHERE (objectproperty(c.id, 'IsUserTable') = 1) AND 
      (c.id = OBJECT_ID('你的表名'))

 

如果要查视图的话, 要修改一下where条件,  把where的objectproperty放到上面增加一个case判断,  AS 出类型

SELECT     CASE WHEN (OBJECTPROPERTY(c.id, 'IsUserTable') = 1) THEN 'Table' WHEN (OBJECTPROPERTY(c.id, 'IsView') = 1) THEN 'View' END AS 类型, OBJECT_NAME(c.id) 
                      AS 表名, c.name AS 字段名, t.name AS 数据类型, c.prec AS 长度
FROM         sys.syscolumns AS c INNER JOIN
                      sys.systypes AS t ON c.xusertype = t.xusertype
WHERE     (c.id = OBJECT_ID('View_1'))

(OBJECTPROPERTY(c.id, ‘IsUserTable’) = 1) 是表,  (OBJECTPROPERTY(c.id, ‘IsView’) = 1) 是视图

关于 OBJECTPROPERTY 的详细用法和参数, 请查看: http://technet.microsoft.com/zh-cn/library/ms176105(v=sql.90).aspx

推荐一个正则表达式测试/验证工具

这几天代码里用到很多正则表达式,需要验证,直接在程序里调试太麻烦。

比如:C#中用正则表达式取页面下拉菜单(select)中的值 – http://bohu.net/blog/8815

找到了这个验证工具:

正则表达式测试器 – http://deerchao.net/tools/regex_tester/index.htm
说明:该工具允许你测试和分析正则表达式。