SELECT语句中的语法错误

时间:2016-05-19 12:31:59

标签: sql-server tsql

凭借我有限的SQL知识,我无法弄清楚这一点。以下是什么问题:

DECLARE @Id int
DECLARE @Name varchar(40)

WHILE EXISTS
        (
        SELECT TOP 1 @Name = Name, @Id=ID FROM MyTable c WHERE <CONDITION>
        )
BEGIN
    SOME MORE SQL using @Id and @Name
END

我在@Name = Name

附近收到语法错误

修改

要为问题添加更多上下文,我有两个名为Category (ID, Name, ParentID)Account(ID, Name, CategoryID)的表。

Categories有3个等级。

  1. 分类
  2. 子类别
  3. 这是使用递归关系(ParentID&gt; CategoryID)实现的。要解决的问题是,如果有任何属于X类({2级)的Accounts,我们必须

    1. 创建一个与X
    2. 同名的子类别Y(级别3)
    3. 让Y成为那个X的孩子
    4. 将所有帐户从X移至Y
    5. 这是我写的原始剧本:

      DECLARE @Id int
      DECLARE @Name varchar(40)
      
      WHILE EXISTS(
              SELECT TOP 1 @Name=Name, @Id=CategoryID FROM Category c WHERE 
              ParentID = (SELECT TOP 1 CategoryID FROM Category WHERE Name = 'Root') AND
              (SELECT COUNT(*) FROM Account WHERE CategoryID = c.CategoryID) > 0
              )
      BEGIN
          INSERT INTO Category(Name, ParentID) VALUES(@Name, @Id)
          UPDATE Account SET CategoryID = @@IDENTITY WHERE CategoryID = @Id  
      END
      

4 个答案:

答案 0 :(得分:2)

您可以使用CURSOR循环:

CREATE TABLE MyTable(ID INT, Name VARCHAR(100));
INSERT INTO Mytable(ID, Name) VALUES (1,10),(2,20);

DECLARE @Id int;
DECLARE @Name varchar(40);

DECLARE cur CURSOR FAST_FORWARD FOR SELECT Name,ID FROM MyTable c WHERE 1=1;

OPEN cur;
FETCH NEXT FROM cur INTO @Id, @Name;

WHILE @@FETCH_STATUS = 0
BEGIN
   SELECT @Id,@Name;   

   FETCH NEXT FROM cur INTO @Id, @Name;
END;

CLOSE cur;
DEALLOCATE cur;

LiveDemo

请注意,没有明确TOP 1的{​​{1}}可能会在执行之间产生不同的结果。

EXISTS

  

EXISTS子查询

请注意,ORDER BY不是子查询,而是赋值。

SELECT @ID = id, @Name = Name

LiveDemo 2

答案 1 :(得分:1)

没有必要使用While,你可以使用if条件代替while这样 - “

DECLARE @Id int
DECLARE @Name varchar(40)

SELECT TOP 1 @Name = Name, @Id=ID FROM MyTable c WHERE <CONDITION>

-- Now Check for @Name and @ID
IF ISNULL(@Name, '') <> '' AND ISNULL(@Id, 0) <> 0
BEGIN
      SOME MORE SQL using @Id and @Name
END

<强> EDITED

IF EXISTS(SELECT 1 FROM Category c 
            WHERE ParentID = (SELECT TOP 1 CategoryID FROM Category WHERE Name = 'Root')  
            AND (SELECT COUNT(*) FROM Account WHERE CategoryID = c.CategoryID) > 0
        )
BEGIN

     SELECT TOP 1 @Name=Name, @Id=CategoryID FROM Category c 
        WHERE ParentID = (SELECT TOP 1 CategoryID FROM Category WHERE Name = 'Root') 
        AND (SELECT COUNT(*) FROM Account WHERE CategoryID = c.CategoryID) > 0

    INSERT INTO Category(Name, ParentID) 
      VALUES(@Name, @Id)

    SET @CategoryID = SCOPE_IDENTITY()

    UPDATE Account SET CategoryID = @CategoryID WHERE CategoryID = @Id  

END

答案 2 :(得分:1)

SELECT @local_variable (Transact-SQL)

  

不能使用包含变量赋值的SELECT语句   也执行典型的结果集检索操作。

在这里你使用EXISTS来检索数据,所以我猜你不能在子查询中使用赋值。

尝试使用BREAK实现等效的WHILE TRUE循环。

{{1}}

答案 3 :(得分:0)

将此用于检查记录存在

WHILE EXISTS
    (
    SELECT TOP 1 * FROM MyTable c WHERE <CONDITION>
    )
BEGIN
    SELECT TOP 1 @Name = Name, @Id=ID FROM MyTable c WHERE <CONDITION>

-- and do here what you want
END