Criar um cursor que atualiza um campo char na tabela ESCOLA

jonathas moura 21 Reputation points
2020-08-25T12:04:49.62+00:00

Olá, estou tentando criar um CURSOR para fins didáticos que atualiza um campo Char na minha tabela ESCOLA conforme a quantidade de níveis de ensino na tabela ESCOLA_NIVELENSINO.

Qualquer ajuda é bem vinda pois a ideia é eu fixar bem o conhecimento, vou deixar abaixo o código que eu estava tentando fazer e também as tabelas com os valores de inserts.

BEGIN TRANSACTION
DECLARE @CODIGO_ESCOLA INT
DECLARE @DESCRICAO VARCHAR(50)
DECLARE @CODIGO_CIDADE INT
DECLARE @NIVEL CHAR(1)

DECLARE CURSOR_ATIVIDADE_INTEGRADORA CURSOR FOR
SELECT
CODIGO_ESCOLA,
DESCRICAO,
CODIGO_CIDADE,
NIVEL
FROM ESCOLA

OPEN CURSOR_ATIVIDADE_INTEGRADORA

FETCH NEXT FROM CURSOR_ATIVIDADE_INTEGRADORA INTO
@CODIGO_ESCOLA, @DESCRICAO, @CODIGO_CIDADE, @NIVEL
WHILE @@Fetch _STATUS = 0
BEGIN
DECLARE CURSOR_COD_ESCOLA_ENSINO CURSOR FOR
SELECT ENV.CODIGO_NIVEL_ENSINO
FROM ESCOLA_NIVELENSINO ENV
INNER JOIN ESCOLA E
ON ENV.CODIGO_ESCOLA = E.CODIGO_ESCOLA
OPEN CURSOR_COD_ESCOLA_ENSINO

IF @CODIGO_NIVEL_ENSINO < 3
UPDATE ESCOLA
SET NIVEL = @NIVEL
WHERE CODIGO_NIVEL_ENSINO = @CODIGO_NIVEL_ENSINO
ELSE
IF @CODIGO_NIVEL_ENSINO >= 3 AND @CODIGO_NIVEL_ENSINO <=4
UPDATE ESCOLA
SET NIVEL = @NIVEL
WHERE CODIGO_NIVEL_ENSINO = @CODIGO_NIVEL_ENSINO
ELSE
UPDATE ESCOLA
SET NIVEL = @nivel
WHERE CODIGO_NIVEL_ENSINO = @CODIGO_NIVEL_ENSINO
FETCH NEXT FROM CURSOR_EXERCICIO_GRUPO INTO
@CODIGO, @nome , @VALOR, @ESTOQUE

END
CLOSE CURSOR_ATIVIDADE_INTEGRADORA
DEALLOCATE CURSOR_ATIVIDADE_INTEGRADORA

SELECT * FROM ESCOLA
ROLLBACK

My tables in database there are:

CREATE TABLE ESCOLA
(
CODIGO_ESCOLA BIGINT NOT NULL,
DESCRICAO VARCHAR(50),
CODIGO_CIDADE BIGINT,
CONSTRAINT PK_CODIGO_ESCOLA PRIMARY KEY(CODIGO_ESCOLA),
CONSTRAINT FK_CIDADE FOREIGN KEY(CODIGO_CIDADE) REFERENCES CIDADE(CODIGO_CIDADE)
)

CREATE TABLE ESCOLA_NIVELENSINO
(
CODIGO_ESCOLA BIGINT,
CODIGO_NIVEL_ENSINO BIGINT,
CONSTRAINT PK_CODESCOLA_CODNVENSINO PRIMARY KEY(CODIGO_ESCOLA, CODIGO_NIVEL_ENSINO),
CONSTRAINT FK_CODIGO_ESCOLA FOREIGN KEY(CODIGO_ESCOLA) REFERENCES ESCOLA(CODIGO_ESCOLA),
CONSTRAINT FK_CODIGO_NIVEL_ENSINO FOREIGN KEY(CODIGO_NIVEL_ENSINO) REFERENCES NIVEL_ENSINO(CODIGO_NIVEL_ENSINO)
)

CREATE TABLE NIVEL_ENSINO
(
CODIGO_NIVEL_ENSINO BIGINT NOT NULL,
DESCRICAO VARCHAR(50),
CONSTRAINT PK_NIVEL_ENSINO PRIMARY KEY(CODIGO_NIVEL_ENSINO)
)

The inserts values:

INSERT INTO NIVEL_ENSINO VALUES
(1,'Ensino fundamental'),
(2,'Ensino Médio'),
(3,'Ensino Técnico'),
(4,'Ensino Superior')

INSERT INTO ESCOLA VALUES
(1, 'ufrj ', 1),
(2, 'ufrgs ', 4),
(3, 'USP ', 3),
(4, 'Escolinha do Professor Raimundo', 10),
(5, 'Escola do Rock', 7)

INSERT INTO ESCOLA_NIVELENSINO VALUES
(1, 3),
(1, 4),
(2, 3),
(2, 4),
(3, 3),
(4, 1),
(4, 2),
(4, 3),
(5, 1),
(5, 2)

Developer technologies | Transact-SQL
SQL Server | Other
{count} votes

2 answers

Sort by: Most helpful
  1. Erland Sommarskog 121.9K Reputation points MVP Volunteer Moderator
    2020-08-25T21:55:57.317+00:00

    The expected language of this forum is English. I can read a little bit of Portuguese, but enough to really understand what you want to do. It would certainly have helped to see the expected results.

    Nor I am really able to understand your code. Normally, when there are two cursors, there are also two WHILE loops, nested to each other. And the inner cursor usually refers to variables fetched from the outer.

    On the other hand, cursors is not something you use very often, and I suspect that this is something that can be solved in a single SQL statement.

    0 comments No comments

  2. EchoLiu-MSFT 14,621 Reputation points
    2020-08-26T09:03:25.783+00:00

    Hi @jonathas moura

    In order to facilitate understanding, the most expected language on the TSQLQ&A forum is English.

    Cursor as a backup method, when the while loop, subquery, temporary table, table variable, custom function or other methods can not achieve certain queries, you can use the cursor to achieve. Your problem is easy to achieve with cte, the cursor is not the most best choice:

    WITH CTE   
    AS (SELECT CODIGO_ESCOLA, COUNT(CODIGO_NIVEL_ENSINO) AS ECOUNT  
        FROM ESCOLA_NIVELENSINO  
        GROUP BY CODIGO_ESCOLA)  
          
    UPDATE a  
    SET a.NIVEL = CASE WHEN c.ECOUNT >= 3 THEN 'A' WHEN c.ECOUNT = 2 THEN 'B' ELSE 'C' END  
    FROM ESCOLA a  
    LEFT JOIN CTE  c  
    ON a.CODIGO_ESCOLA = c.CODIGO_ESCOLA  
          
    SELECT * FROM ESCOLA  
    

    20551-image.png

    Best Regards
    Echo

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.