从MySQL切换到SQLServer:难度级别?

时间:2014-07-28 07:02:10

标签: mysql sql sql-server

我已经使用UI转换为C#构建任何内容。到目前为止,我只是原生C ++。而且我在数据库方面只使用MySQL和SQLite。

我很想切换到只有微软的堆栈,因为我认为C#+ SQLServer相处得更好。

所以我设置了一个LocalDB实例来从MySQL切换一些表来感受事物。显然,在使用SQLServer的15分钟内,我设法获得了预期的WTF时刻:

  1. 没有IF NOT EXISTS这样的东西。您需要将CREATE TABLE包裹在一个疯狂的IF中以复制该功能。 CONSTRAINTS
  2. 也是如此
  3. UNIQUE列会考虑NULL,因此您只能拥有一个NULL。您需要使用NON-CLUSTERED UNIQUE设置一个特殊的WHERE来复制预期的NULL不存在的功能,并且您无法对其进行比较。
  4. 没有INSERT IGNORE这样的东西。您在实际的IGNORE_DUP_KEY=ON键上设置了UNIQUE标记。
  5. 同一个表中的ON UPDATE CASCADE个外键没有ON DELETE CASCADEPRIMARY KEY。我知道你不经常更新主键,但没有DELETE CASCADE
  6. 样品

    CREATE TABLE t0 
    (
        id   INTEGER NOT NULL IDENTITY(1,1) PRIMARY KEY,
        parent_id INTEGER DEFAULT NULL
            references t0 (id) on delete cascade on update cascade
    );
    
    1. 几年前我尝试使用SQLServer,但无法找到如何对结果进行分页(除了TOP。现在我看到他们添加了OFFSET + NEXT来做到这一点。
    2. 这只需要15分钟的测试时间。

      问题是:

      它是这样的吗?微软是否真的按照自己的方式使用SQLServer? (他们已经在IE上完成了十多年)并不是说我希望获得完整的查询级别兼容性,但严重的是......拥有INSERT IGNORE或{{有多难“ 1}}或将CREATE TABLE IF NOT EXISTS视为无效而不是实际值?

      任何移动的人都可以分享一些提示以实现更顺畅的过渡,或者我应该坚持NULL,我已经成为朋友了一段时间......但是GPL?

1 个答案:

答案 0 :(得分:4)

这并不难。 SQL服务器有许多MySQL没有的额外功能。
CTE,可写CTE,递归CTE等

您的表格,您可以使用nHibernate等工具或数据库优先实体框架轻松地重新创建/迁移。
当然,它需要手动修复的百万件小事(如独特的索引) 您实际上可以创建过滤的唯一索引(where your_column is not null

此外,SQL-Server不会为您截断过长的字符串,这可能需要一些丑陋的应用程序代码管道。
如果使用自动增量ID,也需要手动管道。

但主要问题是你的观点和程序。
这是一项非常多的手工工作,因此非常耗时且容易出错 此外,在SQL-Server中,你几乎可以忘记标量函数,因为它们在任何方面都太慢了(它们对于一些东西很有用)。

问题主要是在应用程序代码中使用System.Data.Common中的抽象类而不是System.Data.SqlClient
因此,如果您的应用程序使用MySQL.Data.MySqlClient,或者使用System.Data.SqlClient的应用程序,并且您想要从SQL服务器切换到SQL服务器,那么您必须重新编写应用程序代码,而不仅仅是SQL 这就是为什么您应该始终使用System.Data.Common而不是"Namespace of the day".SqlConnection

的原因

对于分页,SQL-Server 2012+支持ANSI-SQL分页方法:

SELECT
     [TransactionID]
    ,[ProductID]
    ,[ReferenceOrderID]
    ,[ReferenceOrderLineID]
    ,[TransactionDate]
    ,[TransactionType]
    ,[Quantity]
    ,[ActualCost]
    ,[ModifiedDate]
FROM [Production].[TransactionHistoryArchive]
ORDER BY [TransactionID]
OFFSET 5001 ROWS
FETCH NEXT 100 ROWS ONLY 

在SQL-server 2012之前,您必须使用CTE' s:

;WITH CTE AS (
 SELECT
         [TransactionID]
        ,[ProductID]
        ,[ReferenceOrderID]
        ,[ReferenceOrderLineID]
        ,[TransactionDate]
        ,[TransactionType]
        ,[Quantity]
        ,[ActualCost]
        ,[ModifiedDate]
        ,ROW_NUMBER() OVER (ORDER BY ActualCost DESC) AS rn 
    FROM [Production].[TransactionHistoryArchive]
)
SELECT * FROM CTE WHERE rn BETWEEN @min_row AND @max_row

要创建一个表(如果它不存在),您需要将表创建代码放入动态SQL:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T_Verbs]') AND type in (N'U'))
BEGIN

CREATE TABLE [dbo].[T_Verbs](
    [Id] [int] NULL,
    [Infinitive] [nvarchar](500) NULL,
    [FirstPerson] [nvarchar](500) NULL,
    [SecondPerson] [nvarchar](500) NULL,
    [ThirdPerson] [nvarchar](500) NULL,
    [Singular] [bit] NULL,
    [Plural] [bit] NULL
) ON [PRIMARY]
END



IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[T_Verbs]') AND type in (N'U'))
BEGIN
EXEC('
CREATE TABLE [dbo].[T_Verbs](
    [Id] [int] NULL,
    [Infinitive] [nvarchar](500) NULL,
    [FirstPerson] [nvarchar](500) NULL,
    [SecondPerson] [nvarchar](500) NULL,
    [ThirdPerson] [nvarchar](500) NULL,
    [Singular] [bit] NULL,
    [Plural] [bit] NULL
) ON [PRIMARY]
');
END


GO

关于切换到SQL-Server:为什么?
这只是一个过于昂贵的许可噩梦 你在MySQL方面做得更好 但是,如果您需要数据完整性,MySQL和Linux等内容。符合ANSI标准的分页和CTE,数组,关联数组,JSON等,我转而使用PostgreSQL。

在我看来,当你需要它提供的商业智能功能时,SQL服务器才真正好用(不要期望BI网络版与除InternetExplorer之外的任何东西都真正兼容[QuirksMode,顺便说一句] ),或者当你有很多客户使用SQL服务器并且不想要别的东西时。