Mysql 如果为';它不存在

Mysql 如果为';它不存在,mysql,sql-server,stored-procedures,Mysql,Sql Server,Stored Procedures,我想编写一个过程,在列不存在的情况下向表中添加一个新列。我一开始是为MySQL编写的,它工作得很成功,但当我尝试为SQL SERVER编写相同的过程时,我遇到了一些语法错误,而且我不确定SQL SERVER过程是否正确,是否能完成MySQL的相同工作 MySQL过程: SET @dbname = DATABASE(); SET @tablename = "my_table"; SET @columnname = "my_field"; SET @preparedStatement = (SELE

我想编写一个过程,在列不存在的情况下向表中添加一个新列。我一开始是为MySQL编写的,它工作得很成功,但当我尝试为SQL SERVER编写相同的过程时,我遇到了一些语法错误,而且我不确定SQL SERVER过程是否正确,是否能完成MySQL的相同工作

MySQL过程:

SET @dbname = DATABASE();
SET @tablename = "my_table";
SET @columnname = "my_field";
SET @preparedStatement = (SELECT IF(
  (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      (table_name = @tablename)
      AND (table_schema = @dbname)
      AND (column_name = @columnname)
  ) > 0,
  "SELECT 1",
  CONCAT("ALTER TABLE ", @tablename, " ADD ", @columnname, " INT UNSIGNED NOT NULL;")
));
PREPARE alterIfNotExists FROM @preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists;
DECLARE @dbname varchar(128), @tablename varchar(11), @columnname varchar(11), @preparedStatement varchar(max);
SET @dbname = DB_NAME();
SET @tablename = "my_table";
SET @columnname = "my_field";
SET @preparedStatement = (SELECT CASE(
  (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      (table_name = @tablename)
      AND (table_schema = @dbname)
      AND (column_name = @columnname)
  ) > 0,
  "SELECT 1",
  CONCAT("ALTER TABLE ", @tablename, " ADD ", @columnname, " INT UNSIGNED NOT NULL;")
));
EXEC sp_prepare @preparedStatement;
SQL SERVER过程:

SET @dbname = DATABASE();
SET @tablename = "my_table";
SET @columnname = "my_field";
SET @preparedStatement = (SELECT IF(
  (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      (table_name = @tablename)
      AND (table_schema = @dbname)
      AND (column_name = @columnname)
  ) > 0,
  "SELECT 1",
  CONCAT("ALTER TABLE ", @tablename, " ADD ", @columnname, " INT UNSIGNED NOT NULL;")
));
PREPARE alterIfNotExists FROM @preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists;
DECLARE @dbname varchar(128), @tablename varchar(11), @columnname varchar(11), @preparedStatement varchar(max);
SET @dbname = DB_NAME();
SET @tablename = "my_table";
SET @columnname = "my_field";
SET @preparedStatement = (SELECT CASE(
  (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      (table_name = @tablename)
      AND (table_schema = @dbname)
      AND (column_name = @columnname)
  ) > 0,
  "SELECT 1",
  CONCAT("ALTER TABLE ", @tablename, " ADD ", @columnname, " INT UNSIGNED NOT NULL;")
));
EXEC sp_prepare @preparedStatement;
我在第12行发现大于运算符的语法错误:

Msg 102,15级,状态1,第12行'>'附近的语法不正确


您的SQL有很多错误:

首先,SQLServer对文本字符串使用单引号(

CASE
表达式使用格式
CASE WHEN{expr}然后{expr}ELSE[当{expr}然后{expr}][然后{expr}]END
CASE{expr}当…
;你的版本格式非常错误

SQL Server中不存在未签名的数据类型。您只进行了签名(除了
tinyint
,即0-255)

另外,
sp\u prepare
不是正确的函数,您需要
sp\u executesql

最后,我用
QUOTENAME
包装了对象名以避免注入,并将数据类型更改为
sysname
(aka
nvarchar(128)
),并将文本字符串设置为
nvarchar
N'
而不是
'
)。这让你:

DECLARE @dbname sysname,
        @tablename sysname,
        @columnname sysname,
        @preparedStatement nvarchar(MAX);
SET @dbname = DB_NAME();
SET @tablename = N'my_table';
SET @columnname = N'my_field';
SET @preparedStatement = CASE
                              WHEN (SELECT COUNT(*)
                                    FROM INFORMATION_SCHEMA.COLUMNS
                                    WHERE (TABLE_NAME = @tablename)
                                      AND (TABLE_SCHEMA = @dbname)
                                      AND (COLUMN_NAME = @columnname)) = 0 THEN CONCAT(N'ALTER TABLE ', QUOTENAME(@tablename), N' ADD ', QUOTENAME(@columnname), N' INT NOT NULL;')
                         END;
EXEC sp_executesql @preparedStatement;

您的SQL有很多错误:

首先,SQLServer对文本字符串使用单引号(

CASE
表达式使用格式
CASE WHEN{expr}然后{expr}ELSE[当{expr}然后{expr}][然后{expr}]END
CASE{expr}当…
;你的版本格式非常错误

SQL Server中不存在未签名的数据类型。您只进行了签名(除了
tinyint
,即0-255)

另外,
sp\u prepare
不是正确的函数,您需要
sp\u executesql

最后,我用
QUOTENAME
包装了对象名以避免注入,并将数据类型更改为
sysname
(aka
nvarchar(128)
),并将文本字符串设置为
nvarchar
N'
而不是
'
)。这让你:

DECLARE @dbname sysname,
        @tablename sysname,
        @columnname sysname,
        @preparedStatement nvarchar(MAX);
SET @dbname = DB_NAME();
SET @tablename = N'my_table';
SET @columnname = N'my_field';
SET @preparedStatement = CASE
                              WHEN (SELECT COUNT(*)
                                    FROM INFORMATION_SCHEMA.COLUMNS
                                    WHERE (TABLE_NAME = @tablename)
                                      AND (TABLE_SCHEMA = @dbname)
                                      AND (COLUMN_NAME = @columnname)) = 0 THEN CONCAT(N'ALTER TABLE ', QUOTENAME(@tablename), N' ADD ', QUOTENAME(@columnname), N' INT NOT NULL;')
                         END;
EXEC sp_executesql @preparedStatement;

另一种查看SQL并在IMO中使其更易于阅读的方法是将CASE语句转换为存在性检查

DECLARE @dbname varchar(128), @SchemaName varchar(30),  @tablename varchar(30), @columnname varchar(30), @preparedStatement nvarchar(max);
    SET @dbname = DB_NAME();
    SET @SchemaName = 'dbo';
    SET @tablename = 'myTable';
    SET @columnname = 'myColumn';


    IF NOT EXISTS(
        SELECT * FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA LIKE @SchemaName
        AND TABLE_NAME LIKE @tablename
        AND COLUMN_NAME LIKE @columnname
    )
    BEGIN
     SET @preparedStatement =  CONCAT('ALTER TABLE ', @tablename, ' ADD ', @columnname, ' INT UNSIGNED NOT NULL;')
     EXEC sp_executesql @preparedStatement;
    END

另一种查看SQL并在IMO中使其更易于阅读的方法是将CASE语句转换为存在性检查

DECLARE @dbname varchar(128), @SchemaName varchar(30),  @tablename varchar(30), @columnname varchar(30), @preparedStatement nvarchar(max);
    SET @dbname = DB_NAME();
    SET @SchemaName = 'dbo';
    SET @tablename = 'myTable';
    SET @columnname = 'myColumn';


    IF NOT EXISTS(
        SELECT * FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA LIKE @SchemaName
        AND TABLE_NAME LIKE @tablename
        AND COLUMN_NAME LIKE @columnname
    )
    BEGIN
     SET @preparedStatement =  CONCAT('ALTER TABLE ', @tablename, ' ADD ', @columnname, ' INT UNSIGNED NOT NULL;')
     EXEC sp_executesql @preparedStatement;
    END

您使用的是哪一版本的SQL server?@StuartGrant version 14您使用的是哪一版本的SQL server?@StuartGrant version 14谢谢,我原以为我的代码中会有很多错误,因为我没有SQL server方面的经验。上面的过程成功地执行了,但不幸的是,没有改变表。@Mohammad,这是因为CASE语句中的逻辑被颠倒了。应该可以很容易地将更改>0修改为=0 nice spot@t-clausen.dk谢谢,我希望我的代码中有很多错误,因为我没有SQL SERVER方面的经验。上面的过程成功地执行了,但不幸的是,没有改变表。@Mohammad,这是因为CASE语句中的逻辑被颠倒了。应该很容易将change>0修改为=0Nice spot@t-clausen.dk该变量需要是nvarchar才能使用sp_executesql考虑到SQL的性质,您应该考虑注入。甚至可以将
varchar(30)
注入。变量需要是nvarchar才能使用sp_executesql考虑到SQL的性质,您应该考虑注入。即使是
varchar(30)
也可以被注入。