天道酬勤,学无止境

为什么不要创建将ANSI_PADDING设置为OFF的列?

SQL Prompt是一款实用的SQL语法提示工具。它根据数据库的对象名称、语法和代码片段自动进行检索,为用户提供合适的代码选择。自动脚本设置使代码简单易读--当开发者不大熟悉脚本时尤其有用。本文介绍了不要创建将ANSI_PADDING设置为OFF的列。

查找永久更改表中某些数据类型检索方式的连接设置,这有点奇怪,但是如果在创建临时或永久表时使用SET ANSI_PADDING OFF,就会发生这种情况。在创建表时,由于设置不当,或者偶然使用带有DBLib连接的旧应用程序,这会导致表中的某些列从那时起奇怪地或不一致地处理某些字符串或二进制数据类型的尾随空格。

此选项已被弃用,在某些时候,它将被删除(它将始终为“on”)。SQL Prompt具有不赞成使用的语法规则DEP013,它将警告您使用此选项以及其他不赞成使用的SET选项。

SQL Prompt使用教程:为什么不要创建将ANSI_PADDING设置为OFF的列?

什么是ANSI填充?为什么?

在SQL的早期,如何处理字符串的问题引起了争议。定义和固定字符串长度的CHAR数据类型旨在使数据检索简单而有效。字符串以指定的长度存储在CHAR数据类型中。对于较短的字符串,数据类型中所有剩余的字符位置都用空格(CHAR)或零(BINARY)填充。这些填充空格是字符串的一部分吗?如果不是,您如何区分故意填充空格的值和自动填充的值?

SQL的早期实现通常在检索数据时修剪掉CHAR中的所有尾随空格,除非该列是NOT NULL。但是,很明显,为了符合ANSI SQL标准,必须对此进行更改。NIST测试套件检查是否始终填充CHAR数据类型,并且对于CHAR或VARCHAR数据类型,用户输入的尾随空格都不会被截断。SQL Server决定,为了遵守规则,将随数据一起检索任何尾随空格(无论是故意还是作为填充自动添加的),对于二进制数据类型的尾随零也是如此。但是,由于在旧的体制下编写了太多代码,因此Transact-SQL中引入了一种称为ANSI_PADDING的设置。当它关闭时,它允许此旧代码照常工作。似乎每个人都很高兴。

一旦有关CHAR数据类型的ANSI-ISO标准争议平息下来,就会引入新的数据类型和新的表类型。ANSI_PADDING争议仅影响当时存在的类型,而用户为此目的定义的长度。现在可以将字符串存储为NVARCHAR、VARCHAR、NCHAR或CHAR的定义大小。二进制数据可以存储为BINARY或VARBINARY的定义大小。对于CHAR(n)、BINARY(n)、VARCHAR(n)或VARBINARY(n)的较早数据类型,在创建表时ANSI_PADDING选项的设置会影响SQL Server随后处理这些字符串的方式。

但是,后来的NCHAR、NVARCHAR、NTEXT、TEXT或IMAGE数据类型并非如此。未定义长度的类型VARBINARY(MAX)、VARCHAR(MAX)和NVARCHAR(MAX)也不受影响。

旧数据库开发人员真正需要关闭ANSI填充的唯一用途是无需使用该RTRIM()功能即可进行字符串连接。避免必须使用RTRIM()函数似乎是个好主意,但是填充规则的行为与有可空列的行为不一致。另外,随着新类型的表的引入,没有人愿意使它们向后兼容,因此适用的规则通常在ANSI_PADDING关闭时对表变量根本不起作用。同样,如果您尝试在计算列或索引视图上创建或更改索引,则很可能会陷入困境。如果您将ANSI_PADDING设置为OFF,则根本不允许这样做。

那么,规则是什么?

ANSI标准的简单行为是,对于固定宽度类型插入的数据,总是用尾随空格或零填充到指定长度,然后,对于所有数据类型,任何尾随空格或零都被视为数据的一部分,依此类推。当SQL Server将数据检索到内存时,将永远不会修剪它们。

如果在创建表和列时将ANSI_PADDING切换为OFF,则行为将变得更加复杂。幸运的是,是否存在尾随空格不会影响WHERE子句中的字符串比较,因为无论设置什么,这些始终会忽略它们。它也不会对比较产生很大的影响。关闭ANSI_PADDING的主要效果如下:

  • CHAR NOT NULL和BINARY NOT NULL列在插入数据时被填充,并且随后未进行修剪(与ANSI标准相同的行为)

  • 在检索时会修剪可空的CHAR和BINARY列(因此,当然在插入时不再填充)。您会丢失任何尾随空格或故意添加的零

  • 检索时会修剪VARBINARY和VARCHAR列,因此您会丢失任何尾随空格或故意添加的零

如果您需要说服力,我们可以证明所有这些。

PRINT 'Creating a temporary table with ANSI_PADDING ON';
SET ANSI_PADDING ON;
SET NOCOUNT ON;
CREATE TABLE #OnAnsiPaddingTest
  (
  TenCharsNull CHAR(10) NULL,
  TenCharsNotNull CHAR(10) NOT NULL,
  TenVarcharNull VARCHAR(10) NULL,
  TenVarcharNotNull VARCHAR(10) NOT NULL,
  TenVarbinaryNull VARBINARY(10) NULL,
  TenVarbinaryNotNull VARBINARY(10) NOT NULL
  );
<a id="post-1115931-_Hlk33089691"></a>PRINT 'Now creating identical temp table with ANSI_PADDING OFF';
SET ANSI_PADDING OFF;
SET NOCOUNT ON;
CREATE TABLE #OffAnsiPaddingTest
  (
  TenCharsNull CHAR(10) NULL,
  TenCharsNotNull CHAR(10) NOT NULL,
  TenVarcharNull VARCHAR(10) NULL,
  TenVarcharNotNull VARCHAR(10) NOT NULL,
  TenVarbinaryNull VARBINARY(10) NULL,
  TenVarbinaryNotNull VARBINARY(10) NOT NULL
  );
PRINT 'Now creating identical table variable with ANSI_PADDING OFF';
DECLARE @OffAnsiPaddingTest table
  (
  TenCharsNull CHAR(10) NULL,
  TenCharsNotNull CHAR(10) NOT NULL,
  TenVarcharNull VARCHAR(10) NULL,
  TenVarcharNotNull VARCHAR(10) NOT NULL,
  TenVarbinaryNull VARBINARY(10) NULL,
  TenVarbinaryNotNull VARBINARY(10) NOT NULL
  );
PRINT 'Switching ANSI_PADDING back on'
SET ANSI_PADDING ON;
PRINT 'inserting into both tables'
INSERT INTO #OffAnsiPaddingTest
  (TenCharsNull, TenCharsNotNull, TenVarcharNull, TenVarcharNotNull,
TenVarbinaryNull, TenVarbinaryNotNull)
VALUES
  ('First      ', 'Second    ', 'Third     ', 'fourth    ', 0x1234560000,
0x1234560000), --padded to 10
  ('First', 'Second', 'Third', 'fourth', 0x123456, 0x123456); --no trailing padding
INSERT INTO #OnAnsiPaddingTest
  (TenCharsNull, TenCharsNotNull, TenVarcharNull, TenVarcharNotNull,
TenVarbinaryNull, TenVarbinaryNotNull)
VALUES
  ('First      ', 'Second    ', 'Third     ', 'fourth    ', 0x1234560000,
0x1234560000), --padded to 10
  ('First', 'Second', 'Third', 'fourth', 0x123456, 0x123456); --no trailing padding
INSERT INTO @OffAnsiPaddingTest
  (TenCharsNull, TenCharsNotNull, TenVarcharNull, TenVarcharNotNull,
TenVarbinaryNull, TenVarbinaryNotNull)
VALUES
  ('First      ', 'Second    ', 'Third     ', 'fourth    ', 0x1234560000,
0x1234560000), --padded to 10
  ('First', 'Second', 'Third', 'fourth', 0x123456, 0x123456); --no trailing padding
PRINT 'Selecting from first table, created with ANSI padding ON (<> shows extent of string)'
SELECT '<' + Coalesce(TenCharsNull, '') + '> <' + TenCharsNotNull + '> <'
       + Coalesce(TenVarcharNull, '') + '> <' + TenVarcharNotNull + '> <'
       + Coalesce(Convert(VARCHAR(MAX), TenVarbinaryNull, 2), 'null') + '> <'
       + Convert(VARCHAR(MAX), TenVarbinaryNotNull, 2) + '>' AS AnsiPaddingOn
  FROM #OnAnsiPaddingTest AS APT;
PRINT 'Selecting from second table, created with ANSI padding OFF: Same query'
SELECT '<' + Coalesce(TenCharsNull, 'null') + '> <' + TenCharsNotNull + '> <'
       + Coalesce(TenVarcharNull, 'null') + '> <' + TenVarcharNotNull + '> <'
       + Coalesce(Convert(VARCHAR(MAX), TenVarbinaryNull, 2), 'null') + '> <'
       + Convert(VARCHAR(MAX), TenVarbinaryNotNull, 2) + '>' AS AnsiPaddingOff
  FROM #OffAnsiPaddingTest AS APT;
PRINT 'Selecting from table variable, created with ANSI padding OFF: Same query'
SELECT '<' + Coalesce(TenCharsNull, 'null') + '> <' + TenCharsNotNull + '> <'
       + Coalesce(TenVarcharNull, 'null') + '> <' + TenVarcharNotNull + '> <'
       + Coalesce(Convert(VARCHAR(MAX), TenVarbinaryNull, 2), 'null') + '> <'
       + Convert(VARCHAR(MAX), TenVarbinaryNotNull, 2) + '>' AS AnsiPaddingOff
  FROM @OffAnsiPaddingTest AS APT;
  DROP TABLE #OnAnsiPaddingTest;
DROP TABLE #OffAnsiPaddingTest;

您会看到以下消息:

使用ANSI_PADDING ON创建一个临时表
现在使用ANSI_PADDING OFF创建相同的临时表
现在使用ANSI_PADDING OFF'创建相同的表变量
重新打开ANSI_PADDING
插入两个表
从第一个表中选择,并在ANSI填充为ON的情况下创建(<>显示字符串的范围)
从第二个表中选择,使用ANSI填充OFF创建:同一查询
从表变量中选择,使用ANSI填充OFF创建:相同的查询

结果是这样的:

SQL Prompt使用教程:为什么不要创建将ANSI_PADDING设置为OFF的列?

正确的。与往常一样,在创建表时将ANSI_PADDING设置为ON,我们故意添加尾随空格或零的第一行就不会被裁剪。没有尾随空格的第二行被一致地添加为CHAR和BINARY数据类型,无论是否允许NULL。

第二个结果来自关闭ANSI_PADDING时创建的表。可为空的第一个CHAR列已被修剪。具有NOT NULL约束的CHAR列用空格填充。无论是否可以为空,VARBINARY列都修剪了尾随零。VARCHAR列修剪了尾随空格。

第三个结果来自一个表变量,该变量也是通过将ANSI_PADDING设置为OFF来创建的,该设置完全无害。无论设置如何,它的行为都与ANSI兼容。

如果您正在努力接受所有规则和例外,那么您并不孤单。

查找使用ANSI_PADDING关闭创建的异常列

在访问表时,无论您对ANSI_PADDING进行了何种设置,查询行为都是一致的。该设置将保留在表列中,而连接设置将被忽略。无论使用何种连接设置访问“旧版”数据库,该数据库都能始终如一地运行。我们可以通过查询元数据来检查临时表发生了什么。

USE tempdb
SELECT S.name AS TheColumn,
  Object_Schema_Name(S.object_id) + '.' + Object_Name(S.object_id) AS TableName,
  is_ansi_padded
  FROM sys.columns AS S
    INNER JOIN sys.tables AS t
      ON t.object_id = S.object_id
  WHERE system_type_id IN (165, 167, 173, 175) 
     AND is_ansi_padded = 0; --ansi padding off!!

SQL Prompt使用教程:为什么不要创建将ANSI_PADDING设置为OFF的列?

sys.columns视图中的列如果ANSI_PADDING处于打开状态,则为1;如果关闭,则为0。该查询将非常快速地告诉您数据库是否有设置为ANSI_PADDING off的异常列(只需去掉第一行“USE tempdb”)。

结论

除非有人最终有意或无意关闭ANSI_PADDING的危险消失,否则在从SQL Server中最终删除该功能之前,请始终在执行表CREATE语句之前使用SET ANSI_PADDING ON设置与ANSI行为的连接,但在其他任何地方都不应使用的设置,因为该设置和支持已计划弃用,此时您将无法关闭ANSI兼容性。


受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 您是否对数据库项目使用源代码管理? [关闭](Do you use source control for your database items? [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 改善这个问题 我觉得我的店有个漏洞,因为我们没有一个可靠的过程来对数据库架构更改进行版本控制。 我们进行了大量备份,因此或多或少都涉及到备份,但是以这种方式依赖您的最后一道防线是不明智的做法。 令人惊讶的是,这似乎是一个常见的话题。 我说过的许多商店都忽略了这个问题,因为它们的数据库不会经常更改,并且基本上只是在做一些细致的事情。 但是,我知道那个故事是怎么回事。 事情排错了一切而丢失了只是时间问题。 是否有任何最佳做法? 有哪些对您有用的策略? 回答1 必须阅读使数据库受版本控制。 查看K. Scott Allen的系列文章。 在版本控制方面,数据库通常是二等甚至三等公民。 从我所看到的情况来看,在一百万年内从未想到没有版本控制的情况下编写代码的团队-的确如此-可以完全忽略应用程序所依赖的关键数据库的版本控制需求。 我不知道当数据库未与其余代码完全处于相同的严格源代码控制级别时,如何称呼自己为软件工程师并保持直言不讳。 不要让这种情况发生在您身上。 使您的数据库受版本控制。 回答2 数据库本身? 不 创建它们的脚本,包括静态数据插入,存储过程等; 当然。 它们是文本文件,包含在项目中,并且像其他所有文件一样签入和签出。 当然
  • 向现有列添加身份(Adding an identity to an existing column)
    问题 我需要将表的主键更改为标识列,并且表中已经有许多行。 我有一个脚本来清理ID,以确保它们从1开始是连续的,在我的测试数据库上可以正常工作。 将列更改为具有标识属性的SQL命令是什么? 回答1 您无法更改现有的标识列。 您有2种选择, 创建一个具有标识的新表并删除现有表创建一个具有标识的新列并删除现有列 方法1.(新表)在这里,您可以将现有数据值保留在新创建的标识列上。 请注意,如果不满足“如果不存在”的条件,您将丢失所有数据,因此请确保也将条件放在下拉列表上! CREATE TABLE dbo.Tmp_Names ( Id int NOT NULL IDENTITY(1, 1), Name varchar(50) NULL ) ON [PRIMARY] go SET IDENTITY_INSERT dbo.Tmp_Names ON go IF EXISTS ( SELECT * FROM dbo.Names ) INSERT INTO dbo.Tmp_Names ( Id, Name ) SELECT Id, Name FROM dbo.Names TABLOCKX go SET IDENTITY_INSERT dbo.Tmp_Names OFF go DROP TABLE dbo.Names go Exec sp_rename 'Tmp_Names', 'Names'
  • .NET应用程序中的SQL查询速度较慢,但​​在SQL Server Management Studio中是瞬时的(SQL Query slow in .NET application but instantaneous in SQL Server Management Studio)
    问题 这是SQL SELECT tal.TrustAccountValue FROM TrustAccountLog AS tal INNER JOIN TrustAccount ta ON ta.TrustAccountID = tal.TrustAccountID INNER JOIN Users usr ON usr.UserID = ta.UserID WHERE usr.UserID = 70402 AND ta.TrustAccountID = 117249 AND tal.trustaccountlogid = ( SELECT MAX (tal.trustaccountlogid) FROM TrustAccountLog AS tal INNER JOIN TrustAccount ta ON ta.TrustAccountID = tal.TrustAccountID INNER JOIN Users usr ON usr.UserID = ta.UserID WHERE usr.UserID = 70402 AND ta.TrustAccountID = 117249 AND tal.TrustAccountLogDate < '3/1/2010 12:00:00 AM' ) 基本上,有一个Users表
  • 当IDENTITY_INSERT设置为OFF时,无法在表'table'中为标识列插入显式值(Cannot insert explicit value for identity column in table 'table' when IDENTITY_INSERT is set to OFF)
    问题 执行以下脚本时出现以下错误。 什么是错误,如何解决? Insert table(OperationID,OpDescription,FilterID) values (20,'Hierachy Update',1) 错误: 服务器:消息544,级别16,状态1,第1行当IDENTITY_INSERT设置为OFF时,无法在表'table'中为标识列插入显式值。 回答1 您要为作为标识列的OperationId插入值。 您可以像这样在表上打开标识插入,以便可以指定自己的标识值。 SET IDENTITY_INSERT Table1 ON INSERT INTO Table1 /*Note the column list is REQUIRED here, not optional*/ (OperationID, OpDescription, FilterID) VALUES (20, 'Hierachy Update', 1) SET IDENTITY_INSERT Table1 OFF 回答2 不要将值赋给OperationID,因为它将自动生成。 试试这个: Insert table(OpDescription,FilterID) values ('Hierachy Update',1) 回答3 简单来说,如果您在SQL Server上收到此错误,则运行此查询- SET
  • An explicit value for the identity column in table can only be specified when a column list is used and IDENTITY_INSERT is ON SQL Server(An explicit value for the identity column in table can only be specified when a column list is used and IDENTITY_INSER
    问题 我正在尝试执行此查询 INSERT INTO dbo.tbl_A_archive SELECT * FROM SERVER0031.DB.dbo.tbl_A 但即使我跑了 set identity_insert dbo.tbl_A_archive on 我收到此错误消息 仅当使用列列表且IDENTITY_INSERT为ON时,才能为表'dbo.tbl_A_archive'中的identity列指定一个显式值。 tbl_A是一个行和宽的巨大表,即它有很多列。 我不想手动键入所有列。 我怎样才能使它正常工作? 回答1 概括 除非您使用列列表,否则SQL Server不允许您在标识列中插入显式值。 因此,您有以下选择: 制作列列表(手动或使用工具,请参见下文) 或者 将tbl_A_archive的标识列tbl_A_archive为常规的非标识列:如果表是存档表,并且始终为标识列指定一个显式值,为什么还要使用标识列? 只需使用常规的int即可。 解决方案1的详细信息 代替 SET IDENTITY_INSERT archive_table ON; INSERT INTO archive_table SELECT * FROM source_table; SET IDENTITY_INSERT archive_table OFF; 你需要写 SET IDENTITY_INSERT
  • Improve SQL Server query performance on large tables
    I have a relatively large table (currently 2 million records) and would like to know if it's possible to improve performance for ad-hoc queries. The word ad-hoc being key here. Adding indexs is not an option (there are already indexs on the columns which are queried most commonly). Running a simple query to return the 100 most recently updated records: select top 100 * from ER101_ACCT_ORDER_DTL order by er101_upd_date_iso desc Takes several minutes. See execution plan below: Additional detail from the table scan: SQL Server Execution Times: CPU time = 3945 ms, elapsed time = 148524 ms. The
  • SELECT列表不在GROUP BY子句中,并且包含未聚合的列…与sql_mode = only_full_group_by不兼容(SELECT list is not in GROUP BY clause and contains nonaggregated column … incompatible with sql_mode=only_full_group_by)
    问题 我在装有WAMP Server的Windows PC上使用MySQL 5.7.13进行AM 这是我的问题是执行此查询时 SELECT * FROM `tbl_customer_pod_uploads` WHERE `load_id` = '78' AND `status` = 'Active' GROUP BY `proof_type` 总是会出现这样的错误 SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列'returntr_prod.tbl_customer_pod_uploads.id',该列在功能上不依赖于GROUP BY子句中的列; 这与sql_mode = only_full_group_by不兼容 能否请您告诉我最好的解决方案... 我需要像这样的结果 +----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+ | id | user_id | load_id | bill_id | latitude | langitude | proof_type |
  • 哪个更快/最好? SELECT *或SELECT column1,colum2,column3等(Which is faster/best? SELECT * or SELECT column1, colum2, column3, etc)
    问题 我听说SELECT *在编写SQL命令时通常是不好的做法,因为它可以更有效地SELECT您特别需要的SELECT列。 如果我需要SELECT表中的每一列,我应该使用 SELECT * FROM TABLE 或者 SELECT column1, colum2, column3, etc. FROM TABLE 在这种情况下,效率真的重要吗? 我认为,如果您确实需要所有数据,则SELECT *在内部会更理想,但是我说的是这并没有对数据库的真正了解。 我很好奇这种情况下的最佳做法。 更新:我可能应该指定,我真正想要执行SELECT *的唯一情况是当我从一个表中选择数据时,我知道所有列都将始终需要检索,即使添加了新列也是如此。 但是,鉴于我所看到的答复,这似乎仍然是一个坏主意,并且出于很多技术上的原因,切勿使用SELECT * 。 回答1 选择特定列更好的原因之一是,它增加了SQL Server可以从索引访问数据而不是查询表数据的可能性。 这是我写的一篇文章:真正的原因是选择查询的索引覆盖率很差 更改也不那么容易,因为任何消耗数据的代码都将获得相同的数据结构,而不管您将来对表模式所做的更改如何。 回答2 鉴于你的规范,你选择的所有列,也就是在这个时候几乎没有差别。 但是请意识到,数据库架构确实会发生变化。 如果您使用SELECT *
  • SQL Server查询优化和事务处理
    对于了解掌握SQL的增、删、改、查的语句操作是最基本的,实际生产环境中,我们还会用到一些比较高级的数据处理和查询,包括索引、视图、存储过程和触发器。本篇博文主要如何更好的实现对数据库的操作、诊断及优化。 博文大纲:一、索引;二、视图;三、存储过程;四、触发器;五、事务; 一、索引 索引提供指针以指向存储在表中指定列的数据值,然后根据指定的次序排列这些指针,再跟随指针到达包含该值的列。 1.什么是索引 数据库中的索引与书籍中的目录相似。在一本书中,无需阅读整本书,利用目录就可以快速的查找到所需的信息。在数据库中,索引使数据库程序无须对整个表进行扫描,就可以在其中找到所需的数据。书中的目录就是一个词语列表,其中注明了包含各个词的页码。而数据库中的索引是某个表中一列或若干列值的集合,以及物理表示这些值得数据业的逻辑指针清单。 索引是SQL Server编排数据的内部方法,它为SQL Server提供一种方法来编排查询数据的路由。 索引页是数据库中存储索引的数据页。索引页存放检索数据行的关键字页以及该数据行的地址指针。通过使用索引,可以大大提高数据库的检索速度,改善数据库性能。 2.索引分类 在SQL Server中,常用的索引有: (1)唯一索引 唯一索引不允许两行具有相同的索引值。 如果现有数据中存在重复的键值,则一般情况下大多数数据库不允许创建唯一索引。当新数据使表中的键值重复时
  • 我可以通过使用单引号转义单引号和周围的用户输入来防止SQL注入吗?(Can I protect against SQL injection by escaping single-quote and surrounding user input with single-quotes?)
    问题 我意识到在构建包含用户输入的查询时,参数化SQL查询是清理用户输入的最佳方法,但是我想知道使用用户输入并转义任何单引号并将整个字符串都用单引号引起来是怎么回事。 这是代码: sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'" 用户输入的任何单引号都将替换为双单引号,这消除了用户结束字符串的能力,因此他们可能键入的其他任何内容(例如分号,百分号等)都将成为字符串的一部分,并且实际上并未作为命令的一部分执行。 我们使用的是Microsoft SQL Server 2000,我相信单引号是唯一的字符串定界符,也是避免字符串定界符的唯一方法,因此无法执行用户键入的任何内容。 我看不到有什么方法可以发起针对此的SQL注入攻击,但是我意识到,如果这在我看来像防弹一样,那么其他人可能已经想到了,并且这将是普遍的做法。 此代码有什么问题? 有没有办法使SQL注入攻击超越这种清理技术? 利用此技术的样本用户输入将非常有帮助。 更新: 我仍然不知道有什么方法可以有效地对此代码发起SQL注入攻击。 一些人建议反斜杠可以转义一个单引号,而让另一个反斜杠结束该字符串,以便该字符串的其余部分将作为SQL命令的一部分执行,并且我意识到该方法可以将SQL注入到一个MySQL数据库,但是在SQL Server 2000中
  • 如何强制实体框架插入标识列?(How can I force entity framework to insert identity columns?)
    问题 我想编写一些C#代码以使用一些种子数据初始化数据库。 显然,这将要求在插入时能够设置各种Identity列的值的能力。 我正在使用代码优先的方法。 默认情况下, DbContext处理数据库连接,因此您无法将SET IDENTITY_INSERT [dbo].[MyTable] ON 。 因此,到目前为止,我所做的是使用DbContext构造函数,该构造函数使我可以指定要使用的数据库连接。 然后,我在该数据库连接中将IDENTITY_INSERT设置为ON ,然后尝试使用实体框架插入我的记录。 这是到目前为止我得到的一个例子: public class MyUserSeeder : IEntitySeeder { public void InitializeEntities(AssessmentSystemContext context, SqlConnection connection) { context.MyUsers.Add(new MyUser { MyUserId = 106, ConceptPersonId = 520476, Salutation = "Mrs", Firstname = "Novelette", Surname = "Aldred", Email = null, LoginId = "520476", Password=
  • 使用Rails,如何将主键设置为非整数类型的列?(Using Rails, how can I set my primary key to not be an integer-typed column?)
    问题 我正在使用Rails迁移来管理数据库架构,并且正在创建一个简单的表,在该表中我想使用非整数值作为主键(尤其是字符串)。 为了"134SNW"我的问题,我们假设有一个表employees ,其中雇员由字母数字字符串标识,例如"134SNW" 。 我试过在这样的迁移中创建表: create_table :employees, {:primary_key => :emp_id} do |t| t.string :emp_id t.string :first_name t.string :last_name end 这给了我什么,好像它完全忽略了t.string :emp_id ,并使其成为整数列。 还有其他方法可以让rails为我生成PRIMARY_KEY约束(我正在使用PostgreSQL),而不必在execute调用中编写SQL吗? 注意:我知道最好不要将字符串列用作主键,因此请不要回答只是说要添加一个整数主键。 我仍然可以添加一个,但是这个问题仍然有效。 回答1 不幸的是,我确定如果不使用execute就不可能做到这一点。 为什么它不起作用 通过检查ActiveRecord源,我们可以找到create_table的代码: 在schema_statements.rb中: def create_table(table_name, options={}) ... table
  • Mysql高级-总结
    MySQL事务隔离级别 事务隔离级别脏读不可重复读幻读读未提交(read-uncommitted)是是是不可重复读(read-committed)否是是可重复读(repeatable-read)否否是串行化(serializable)否否否 索引是帮助MYSQL高速获取数据的数据结构,索引本身也很大,不可能完全存储在内存中,因此索引往往以索引文件的形式存在磁盘文件中 索引有哪几种类型? 主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。 唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。 可以通过 ALTER TABLE table_name ADD UNIQUE (column); 创建唯一索引 可以通过 ALTER TABLE table_name ADD UNIQUE (column1,column2); 创建唯一组合索引 普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。 可以通过ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引 可以通过ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);创建组合索引 全文索引: 是目前搜索引擎使用的一种关键技术。
  • 如何将CSV文件导入MySQL表?(How do I import CSV file into a MySQL table?)
    问题 我有一个来自客户端的非标准化事件日志CSV,我正在尝试将其加载到MySQL表中,以便可以将其重构为合理的格式。 我创建了一个名为“ CSVImport”的表,该表的CSV文件的每一列都有一个字段。 CSV包含99列,因此这本身就是一项艰巨的任务: CREATE TABLE 'CSVImport' (id INT); ALTER TABLE CSVImport ADD COLUMN Title VARCHAR(256); ALTER TABLE CSVImport ADD COLUMN Company VARCHAR(256); ALTER TABLE CSVImport ADD COLUMN NumTickets VARCHAR(256); ... ALTER TABLE CSVImport Date49 ADD COLUMN Date49 VARCHAR(256); ALTER TABLE CSVImport Date50 ADD COLUMN Date50 VARCHAR(256); 该表上没有任何约束,并且所有字段都包含VARCHAR(256)值,但包含计数(以INT表示),是/否(以BIT表示),价格(以DECIMAL表示)和文本框()的列除外。由TEXT表示)。 我试图将数据加载到文件中: LOAD DATA INFILE '/home/paul
  • SQL Server-SELECT FROM存储过程(SQL Server - SELECT FROM stored procedure)
    问题 我有一个存储过程返回行: CREATE PROCEDURE MyProc AS BEGIN SELECT * FROM MyTable END 我的实际过程稍微复杂一点,这就是为什么需要一个sproc的原因。 是否可以通过调用此过程来选择输出? 就像是: SELECT * FROM (EXEC MyProc) AS TEMP 我需要使用SELECT TOP X , ROW_NUMBER以及一个附加的WHERE子句来分页数据,而我实际上并不想将这些值作为参数传递。 回答1 您可以使用用户定义的函数或视图代替过程。 一个过程可以返回多个结果集,每个结果集都有自己的模式。 它不适合在SELECT语句中使用。 回答2 你可以 创建一个表变量以保存来自存储过程的结果集,然后将存储的proc的输出插入到table变量中,然后完全像使用其他任何表一样使用表变量... ... SQL .... Declare @T Table ([column definitions here]) Insert @T Exec storedProcname params Select * from @T Where ... 回答3 您需要表值函数或将EXEC插入临时表中: INSERT INTO #tab EXEC MyProc 回答4 您需要声明一个表类型,该表类型包含与存储过程返回的列数相同的列。
  • DBNull的意义是什么?(What is the point of DBNull?)
    问题 在.NET中,存在一个null引用,该引用在任何地方都用来表示一个对象引用为空,然后是DBNull ,它被数据库驱动程序(和其他一些驱动程序)用来表示...几乎一样。 自然,这会引起很多混乱,必须转换转换例程,等等。 那么,最初的.NET作者为什么决定这样做呢? 对我而言,这没有任何意义。 他们的文档也没有任何意义: DBNull类表示不存在的值。 例如,在数据库中,表行中的列可能不包含任何数据。 即,该列被认为根本不存在,而不仅仅是没有值。 DBNull对象表示不存在的列。 此外,COM互操作使用DBNull类来区分表示不存在的值的VT_NULL变体和表示未指定的值的VT_EMPTY变体。 关于“不存在的列”的废话是什么? 有一列存在,只是没有特定行的值。 如果不存在,则尝试访问特定单元而不是DBNull会出现异常! 我可以理解需要区分VT_NULL和VT_EMPTY ,但是为什么不COMEmpty类呢? 这将更适合整个.NET框架。 我想念什么吗? 谁能阐明为什么发明DBNull以及它可以解决什么问题? 回答1 关键是在某些情况下,数据库值为null和.NET Null之间会有区别。 例如。 如果使用ExecuteScalar(返回结果集中第一行的第一列),并且返回null,则表示执行的SQL不返回任何值。 如果返回DBNull,则表示SQL返回了一个值,该值为NULL。
  • attr_accessor和attr_accessible之间的区别(Difference between attr_accessor and attr_accessible)
    问题 在Rails中, attr_accessor和attr_accessible什么attr_accessible ? 据我了解,使用attr_accessor可以为该变量创建getter和setter方法,以便我们可以访问Object.variable或Object.variable = some_value类的变量。 我读到attr_accessible使该特定变量可供外界访问。 有人可以告诉我有什么区别吗 回答1 attr_accessor是一个Ruby方法,该方法生成一个getter和一个setter。 attr_accessible是一种Rails方法,它允许您将值传递给批量分配: new(attrs)或update_attributes(attrs) 。 这是一个批量任务: Order.new({ :type => 'Corn', :quantity => 6 }) 您可以想象该订单可能还具有折扣代码,例如:price_off 。 如果您不将:price_off标记为attr_accessible可以阻止恶意代码执行以下操作: Order.new({ :type => 'Corn', :quantity => 6, :price_off => 30 }) 即使您的表单没有用于:price_off的字段,也可以在默认情况下使用它。
  • SQL Server查询优化与事务处理
    博文目录一、索引二、视图三、存储过程四、系统存储过程五、触发器六、事务七、锁 一、索引 索引提供指针以指向存储在表中指定列的数据值,然后根据指定的次序排列这些指针,再跟随指针到达包含该值的列。 1、什么是索引 数据库中的索引与书籍中的目录相似。在一本书中,无需阅读整本书,利用目录就可以快速的查找到所需的信息。在数据库中,索引使数据库程序无须对整个表进行扫描,就可以在其中找到所需的数据。书中的目录就是一个词语列表,其中注明了包含各个词的页码。而数据库中的索引是某个表中一列或若干列值的集合,以及物理表示这些值得数据业的逻辑指针清单。 索引是SQL Server编排数据的内部方法,它为SQL Server提供一种方法来编排查询数据的路由。 索引页是数据库中存储索引的数据页。索引页存放检索数据行的关键字页以及该数据行的地址指针。通过使用索引,可以大大提高数据库的检索速度,改善数据库性能。 2、索引分类 1)唯一索引 唯一索引不允许两行具有相同的索引值。如果现有数据中存在重复的键值,则一般情况下大多数数据库不允许创建唯一索引。当新数据使表中的键值重复时,数据库也拒绝接收此数据。创建了唯一约束,将自动创建唯一索引。尽管唯一索引有助于找到信息,但是为了获得最佳性能,建议使用主键约束。 2)主键索引 在数据库关系图中为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型
  • 非主键的外键(Foreign Key to non-primary key)
    问题 我有一个保存数据的表,并且其中一个行需要存在于另一个表中。 因此,我想要一个外键来保持引用完整性。 CREATE TABLE table1 ( ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, AnotherID INT NOT NULL, SomeData VARCHAR(100) NOT NULL ) CREATE TABLE table2 ( ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, AnotherID INT NOT NULL, MoreData VARCHAR(30) NOT NULL, CONSTRAINT fk_table2_table1 FOREIGN KEY (AnotherID) REFERENCES table1 (AnotherID) ) 但是,如您所见,我的外键表所在的列不是PK。 有没有一种方法可以创建此外键,或者有更好的方法来维护此引用完整性? 回答1 如果您真的想为非主键创建外键,则它必须是对其具有唯一约束的列。 从在线书籍: 一个FOREIGN KEY约束不必仅链接到另一个表中的PRIMARY KEY约束。 还可以定义它引用另一个表中的UNIQUE约束的列。 因此,在您的情况下,如果您使AnotherID唯一,则将允许它。 如果您不能应用唯一约束,那么您就不走运了
  • Why is some sql query much slower when used with SqlCommand?
    I have a stored procedure that executes much faster from Sql Server Management Studio (2 seconds) than when run with System.Data.SqlClient.SqlCommand (times out after 2 minutes). What could be the reason for this? Details: In Sql Server Management Studio this runs in 2 seconds (on production database): EXEC sp_Stat @DepartmentID = NULL In .NET/C# the following times out after 2 minutes (on production database): string selectCommand = @" EXEC sp_Stat @DepartmentID = NULL"; string connectionString = "server=***;database=***;user id=***;pwd=***"; using (SqlConnection connection = new