Kedarnath M S Ответов: 1

Хранимая процедура с временной таблицей


Я хочу изменить хранимую процедуру без жесткого кодирования имени документа и получить тот же результат.

Что я уже пробовал:

Мой ИП-это:
ALTER PROCEDURE [dbo].[SPEMPIDDETAILS]
AS
BEGIN
    DECLARE @INTSTART AS INTEGER;
    DECLARE @INTSTOP AS INTEGER;

    DECLARE @ENAME AS VARCHAR(50);

    DECLARE @PREFNO AS VARCHAR(50);
    DECLARE @PVAL AS DATE;

    DECLARE @VREFNO AS VARCHAR(50);
    DECLARE @VVAL AS DATE;

    DECLARE @SBREFNO AS VARCHAR(50);
    DECLARE @SBVAL AS VARCHAR(50);

    DECLARE @UVREFNO AS VARCHAR(50);
    DECLARE @UVVAL AS DATE;

    --Temp Table for Save Employee Name
    DECLARE @TEMPTABLEEMPNAME TABLE (INTEMPNAME_ID INT IDENTITY(1,1),
                                     EMPNAME VARCHAR(50))

    --Temp Table for Save ID Ref.No and Validity
    DECLARE @TEMPTABLEEMP TABLE (INTEMPID_ID INT IDENTITY(1,1),
                                 ENAME VARCHAR(50),
                                 PREFNO VARCHAR(50), PVAL DATE, 
                                 VREFNO VARCHAR(50), VVAL DATE,
                                 SBREFNO VARCHAR(50), SBVAL DATE,
                                 UVREFNO VARCHAR(50), UVVAL DATE)

    INSERT INTO @TEMPTABLEEMPNAME(EMPNAME)
        SELECT EMPLOYEE
        FROM EMPIDDETAILS

    SELECT @INTSTART = 1;
    SELECT @INTSTOP = (SELECT COUNT(INTEMPNAME_ID) FROM @TEMPTABLEEMPNAME);

    WHILE @INTSTART <= @INTSTOP
    BEGIN
        SET @ENAME = (SELECT EMPLOYEE 
                      FROM EMPIDDETAILS 
                      WHERE PK_ID = @INTSTART)

        SELECT 
            @PREFNO = (SELECT REF_NO FROM EMPIDDETAILS 
                       WHERE DOCUMENT_TYPE = 'PASSPORT' AND EMPLOYEE = @ENAME),
            @PVAL = (SELECT VALIDITY FROM EMPIDDETAILS 
                     WHERE DOCUMENT_TYPE = 'PASSPORT' AND EMPLOYEE = @ENAME)

        SELECT 
            @VREFNO = (SELECT REF_NO FROM EMPIDDETAILS 
                       WHERE DOCUMENT_TYPE = 'VISA' AND EMPLOYEE = @ENAME),
            @VVAL = (SELECT VALIDITY FROM EMPIDDETAILS 
                     WHERE DOCUMENT_TYPE = 'VISA' AND EMPLOYEE = @ENAME)

        SELECT 
            @SBREFNO = (SELECT REF_NO FROM EMPIDDETAILS 
                        WHERE DOCUMENT_TYPE = 'SEAMAN BOOK' AND EMPLOYEE = @ENAME),
            @SBVAL = (SELECT VALIDITY FROM EMPIDDETAILS 
                      WHERE DOCUMENT_TYPE = 'SEAMAN BOOK' AND EMPLOYEE = @ENAME)

        SELECT 
            @UVREFNO = (SELECT REF_NO FROM EMPIDDETAILS 
                        WHERE DOCUMENT_TYPE = 'USVISA' AND EMPLOYEE = @ENAME),
            @UVVAL = (SELECT VALIDITY FROM EMPIDDETAILS 
                      WHERE DOCUMENT_TYPE = 'USVISA' AND EMPLOYEE = @ENAME)


        INSERT INTO @TEMPTABLEEMP 
        VALUES(@ENAME, @PREFNO, @PVAL, @VREFNO, @VVAL, @SBREFNO, @SBVAL, @UVREFNO, @UVVAL)

        SET @ENAME = 0
        SET @PREFNO = 0
        SET @PVAL = NULL
        SET @VREFNO = 0
        SET @VVAL = NULL
        SET @SBREFNO = 0
        SET @SBVAL = NULL
        SET @UVREFNO = 0
        SET @UVVAL = NULL

        SET @INTSTART = @INTSTART + 1;
    END

    SELECT DISTINCT 
        ENAME AS EMPLOYEE, 
        PREFNO AS REF_NO, PVAL as VALIDITY,
        VREFNO AS REF_NO, VVAL AS VALIDITY,
        SBREFNO AS REF_NO, SBVAL AS VALIDITY,
        UVREFNO AS REF_NO, UVVAL AS VALIDITY
    FROM 
        @TEMPTABLEEMP
END

CHill60

Передать их в качестве параметров СП - Как создать хранимую процедуру SQL Server с параметрами[^]

ZurdoDev

Я не понимаю, о чем вы нас спрашиваете.

1 Ответов

Рейтинг:
2

CHill60

Вы говорите об этом очень многословно. Например

SELECT
    @PREFNO = (SELECT REF_NO FROM EMPIDDETAILS
               WHERE DOCUMENT_TYPE = 'PASSPORT' AND EMPLOYEE = @ENAME),
    @PVAL = (SELECT VALIDITY FROM EMPIDDETAILS
             WHERE DOCUMENT_TYPE = 'PASSPORT' AND EMPLOYEE = @ENAME)
может быть заменен на
SELECT @PREFNO = REF_NO,  @PVAL = VALIDITY FROM EMPIDDETAILS
           WHERE DOCUMENT_TYPE = 'PASSPORT' AND EMPLOYEE = @ENAME
..и то же самое относится к @VREFNO, @VVAL, @SBREF, @SBVAL, @UVREF и @UVVAL

Нет никакой необходимости в столе @TEMPTABLEEMPNAME - вы можете получить информацию, которую вы получаете из этой таблицы непосредственно из EMPIDDETAILS. Например
SELECT @INTSTOP = (SELECT COUNT(distinct(EMPLOYEE)) FROM EMPIDDETAILS);
но это также может привести к проблемам. Вы позже используете
SET @ENAME = (SELECT EMPLOYEE
              FROM EMPIDDETAILS
              WHERE PK_ID = @INTSTART)
где @INSTART итерация от 1 до числа сотрудников-но что делать, если вы удалили запись о сотруднике? Возможно, у вас нет соответствующей записи, и, что более важно, конечный PK_ID в таблице может быть больше, чем количество. Неясно, что такое PK_ID на самом деле ... название подразумевает, что это первичный ключ, но он также выглядит так, как будто он уникален для имя не имя + DOCUMENT_TYPE. В любом случае было бы лучше использовать
SELECT @INTSTOP = (SELECT MAX(PK_ID) FROM EMPIDDETAILS);
чтобы убедиться, что вы не пропустите ни одной записи.

Однако в этом нет никакой необходимости. WHILE заявление. SQL-сервер (большинство, если не все СУБД) Набор на основе - все, что вы хотите сделать с каждой строкой, может быть описано один раз и выполнено против всей таблицы.
Например, это получает те же данные во временную таблицу, что и весь оператор WHILE...
SELECT A.EMPLOYEE, A.REF_NO,  A.VALIDITY, B.REF_NO,  B.VALIDITY, C.REF_NO,  C.VALIDITY, D.REF_NO,  D.VALIDITY
FROM EMPIDDETAILS A
LEFT OUTER JOIN EMPIDDETAILS B ON A.EMPLOYEE=B.EMPLOYEE AND B.DOCUMENT_TYPE = 'VISA'
LEFT OUTER JOIN EMPIDDETAILS C ON A.EMPLOYEE=C.EMPLOYEE AND C.DOCUMENT_TYPE = 'SEAMAN BOOK'
LEFT OUTER JOIN EMPIDDETAILS D ON A.EMPLOYEE=D.EMPLOYEE AND D.DOCUMENT_TYPE = 'USVISA'
WHERE A.DOCUMENT_TYPE = 'PASSPORT'
На самом деле, избавьтесь от временной таблицы все вместе, чтобы весь ваш SP стал
ALTER PROCEDURE [dbo].[SPEMPIDDETAILS]
AS
BEGIN
 
    SELECT A.EMPLOYEE as ENAME, A.REF_NO AS PREFNO,  A.VALIDITY AS PVAL, 
			B.REF_NO AS VREFNO,  B.VALIDITY AS VVAL, 
			C.REF_NO AS SBREFNO, C.VALIDITY SBVAL, 
			D.REF_NO AS UVREFNO, D.VALIDITY AS UVVAL
    FROM EMPIDDETAILS A
    LEFT OUTER JOIN EMPIDDETAILS B ON A.EMPLOYEE=B.EMPLOYEE AND B.DOCUMENT_TYPE = 'VISA'
    LEFT OUTER JOIN EMPIDDETAILS C ON A.EMPLOYEE=C.EMPLOYEE AND C.DOCUMENT_TYPE = 'SEAMAN BOOK'
    LEFT OUTER JOIN EMPIDDETAILS D ON A.EMPLOYEE=D.EMPLOYEE AND D.DOCUMENT_TYPE = 'USVISA'
    WHERE A.DOCUMENT_TYPE = 'PASSPORT'

END

Чтобы вернуться к исходному вопросу, вы можете передать типы документов в качестве параметров вместо жесткого кодирования (см. Как создать хранимую процедуру SQL Server с параметрами[^])

Напр.
CREATE PROCEDURE [dbo].[SPEMPIDDETAILS] 
    @DocType1 varchar(20) = 'PASSPORT', 
	@DocType2 varchar(20) = 'VISA', 
	@DocType3 varchar(20) = 'SEAMAN BOOK', 
	@DocType4 varchar(20) = 'USVISA'
AS
BEGIN
 
	SELECT A.EMPLOYEE as ENAME, A.REF_NO AS PREFNO,  A.VALIDITY AS PVAL, 
			B.REF_NO AS VREFNO,  B.VALIDITY AS VVAL, 
			C.REF_NO AS SBREFNO, C.VALIDITY SBVAL, 
			D.REF_NO AS UVREFNO, D.VALIDITY AS UVVAL
	FROM EMPIDDETAILS A
	LEFT OUTER JOIN EMPIDDETAILS B ON A.EMPLOYEE=B.EMPLOYEE AND B.DOCUMENT_TYPE = @DocType2
	LEFT OUTER JOIN EMPIDDETAILS C ON A.EMPLOYEE=C.EMPLOYEE AND C.DOCUMENT_TYPE = @DocType3
	LEFT OUTER JOIN EMPIDDETAILS D ON A.EMPLOYEE=D.EMPLOYEE AND D.DOCUMENT_TYPE = @DocType4
	WHERE A.DOCUMENT_TYPE = @DocType1

END

Я не очень много комментировал вашу схему таблицы, но я подозреваю, что есть по крайней мере еще один уровень нормализации, который должен быть сделан - см. 1NF, 2NF, 3NF и BCNF в нормализации баз данных / учебник по СУБД | Studytonight[^]