SQL 服务器函数和触发器的问题
Issues with SQL Server functions and triggers
我一直在通过使用 SQL 服务器的 "advanced" 功能和创建函数、触发器来处理这个项目,但是其中两个给我带来了严重的问题。
我应该创建一个包含一个输入参数和 return 一个 table 的函数。该函数本身将 return 每项保险费用(基础、配偶等)的个人费用的摘要、这些费用的总计以及给定员工拥有的家属人数的员工姓名 - 用户输入作为输入参数的家属人数。
CREATE FUNCTION fnInsCosts
(@NoDependants int)
--returns table datatype
RETURNS table
AS
--Set the Return to select the columns and aggregated columns from vwPayRoll as listed in exercise 3 of Module 12 --assignment sheet where Dependants is = to the input variable.
RETURN (SELECT
EmpName,
SUM(BaseCost) AS TotBaseCost, SUM(SpouseIns) AS TotSpouseCost,
SUM(DepIns) AS TotDepCost, SUM(DentalCost) AS TotDentalCost,
SUM(BaseCost * SpouseIns * DepIns * DentalCost) AS TotInsCost
FROM
vwPayroll
WHERE
Dependants = @NoDependants
GROUP BY
Dependants);
SELECT * FROM dbo.fnInsCosts(2);
SELECT * FROM dbo.fnInsCosts(0);-- Unfinished/error with select and EmpName?
这是我尝试 运行 整个事情时遇到的错误:
Msg 156, Level 15, State 1, Procedure fnInsCosts, Line 15
Incorrect syntax near the keyword 'SELECT'.
当我 运行 除了我调用它的部分之外的所有内容时,它会这样说:
Msg 8120, Level 16, State 1, Procedure fnInsCosts, Line 10
Column 'vwPayroll.EmpName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
这是最后一个;我正在创建一个触发器,我需要创建两个 table 副本:
--Test for the existence of a fake table named TempEmpData. If it exists, drop it.
IF OBJECT ID('TempEmpData') IS NOT NULL
DROP TABLE TempEmpData;
--Test for the existence of a fake table named TempWork. If it exists, drop it.
IF OBJECT ID('TempWork') IS NOT NULL
DROP TABLE TempWork;
--Select everything from EmpData into the appropriate fake table
SELECT * INTO TempEmpData FROM EmpData
--Select everything from Work into the appropriate fake table
SELECT * INTO TempWork FROM Work
GO
CREATE TRIGGER TempEmpDate_INSERT_UPDATE_DELETE
ON TempEmpData
AFTER INSERT, UPDATE, DELETE
AS
--(USE THIS CONDITIONAL STRUCTURE- substitute variable names where needed and remove the "--")
IF EXISTS (SELECT * FROM Deleted JOIN TempEmpData ON Deleted.EmpID = TempEmpData.EmpID)
--the correct primary key)
BEGIN;
--Custom error message
THROW 11, 'EmpID is in use; transaction cancelled!', 1;
--rollback the transaction
ROLLBACK TRAN;
END;
ELSE
BEGIN
--Update the appropriate fake table
CREATE TRIGGER TempEmpData_INSERT_UPDATE
ON TempEmpData
AS
--Set the appropriate column to the correct value
--Where the correct primary key is in a subquery selecting that same key from the
--system table that handles inserts
UPDATE TempEmpData
SET BenPlanID = 0;
DELETE TempEmpData
WHERE EmpID = 41;
INSERT TempEmpData
VALUES ('Bill', 'Smith', '11/14/2014', 0, 0, 1, NULL, 2);
SELECT *
FROM TempEmpData
ORDER BY EmpID DESC
END;
错误如下:
Msg 4145, Level 15, State 1, Line 4
An expression of non-boolean type specified in a context where a condition is expected, near 'ID'.
Msg 4145, Level 15, State 1, Line 8
An expression of non-boolean type specified in a context where a condition is expected, near 'ID'.
Msg 156, Level 15, State 1, Procedure TempEmpDate_INSERT_UPDATE_DELETE, Line 17
Incorrect syntax near the keyword 'TRIGGER'.
如有任何见解,我将不胜感激。
您正在使用“新”内联语法创建函数,太棒了!
第一个错误来自缺少“GO”,将函数的创建与调用分开
CREATE FUNCTION fnInsCosts()
--You function code here
GO
SELECT * FROM dbo.fnInsCosts(2);
你的函数中的第二个错误有它的原因——正如 JamesZ 已经指出的——在错误的分组列中:
SELECT EmpName,
SUM(BaseCost) AS TotBaseCost,
SUM(SpouseIns) AS TotSpouseCost,
SUM(DepIns) AS TotDepCost,
SUM(DentalCost) AS TotDentalCost,
SUM(BaseCost * SpouseIns * DepIns * DentalCost) AS TotInsCost
FROM vwPayroll
WHERE Dependants = @NoDependants
GROUP BY EmpName
你看,唯一没有任何聚合函数的列是 EmpName...
最后一个 - JamesZ 再次声明已经是函数名称中缺少的下划线 OBJECT ID
:
IF OBJECT_ID('TempEmpData') IS NOT NULL
在您的代码中,T-SQL 正在搜索“对象”的含义和名为“ID”的函数...(与 IF OBJECT ID('TempWork') IS NOT NULL
相同)
最后一点:在 SO 上,强烈建议每个问题创建一个问题。这个问题应该至少分为两个单独的问题。想想未来的读者搜索类似的问题...
EDIT Ups,还有一个...
你的最后一条错误消息指向一些代码,我不明白你真正想要实现什么...你是从触发器内部创建触发器吗?可能是,无论如何,MERGE
声明是满足您需求的更好方法...
我一直在通过使用 SQL 服务器的 "advanced" 功能和创建函数、触发器来处理这个项目,但是其中两个给我带来了严重的问题。
我应该创建一个包含一个输入参数和 return 一个 table 的函数。该函数本身将 return 每项保险费用(基础、配偶等)的个人费用的摘要、这些费用的总计以及给定员工拥有的家属人数的员工姓名 - 用户输入作为输入参数的家属人数。
CREATE FUNCTION fnInsCosts
(@NoDependants int)
--returns table datatype
RETURNS table
AS
--Set the Return to select the columns and aggregated columns from vwPayRoll as listed in exercise 3 of Module 12 --assignment sheet where Dependants is = to the input variable.
RETURN (SELECT
EmpName,
SUM(BaseCost) AS TotBaseCost, SUM(SpouseIns) AS TotSpouseCost,
SUM(DepIns) AS TotDepCost, SUM(DentalCost) AS TotDentalCost,
SUM(BaseCost * SpouseIns * DepIns * DentalCost) AS TotInsCost
FROM
vwPayroll
WHERE
Dependants = @NoDependants
GROUP BY
Dependants);
SELECT * FROM dbo.fnInsCosts(2);
SELECT * FROM dbo.fnInsCosts(0);-- Unfinished/error with select and EmpName?
这是我尝试 运行 整个事情时遇到的错误:
Msg 156, Level 15, State 1, Procedure fnInsCosts, Line 15
Incorrect syntax near the keyword 'SELECT'.
当我 运行 除了我调用它的部分之外的所有内容时,它会这样说:
Msg 8120, Level 16, State 1, Procedure fnInsCosts, Line 10
Column 'vwPayroll.EmpName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
这是最后一个;我正在创建一个触发器,我需要创建两个 table 副本:
--Test for the existence of a fake table named TempEmpData. If it exists, drop it.
IF OBJECT ID('TempEmpData') IS NOT NULL
DROP TABLE TempEmpData;
--Test for the existence of a fake table named TempWork. If it exists, drop it.
IF OBJECT ID('TempWork') IS NOT NULL
DROP TABLE TempWork;
--Select everything from EmpData into the appropriate fake table
SELECT * INTO TempEmpData FROM EmpData
--Select everything from Work into the appropriate fake table
SELECT * INTO TempWork FROM Work
GO
CREATE TRIGGER TempEmpDate_INSERT_UPDATE_DELETE
ON TempEmpData
AFTER INSERT, UPDATE, DELETE
AS
--(USE THIS CONDITIONAL STRUCTURE- substitute variable names where needed and remove the "--")
IF EXISTS (SELECT * FROM Deleted JOIN TempEmpData ON Deleted.EmpID = TempEmpData.EmpID)
--the correct primary key)
BEGIN;
--Custom error message
THROW 11, 'EmpID is in use; transaction cancelled!', 1;
--rollback the transaction
ROLLBACK TRAN;
END;
ELSE
BEGIN
--Update the appropriate fake table
CREATE TRIGGER TempEmpData_INSERT_UPDATE
ON TempEmpData
AS
--Set the appropriate column to the correct value
--Where the correct primary key is in a subquery selecting that same key from the
--system table that handles inserts
UPDATE TempEmpData
SET BenPlanID = 0;
DELETE TempEmpData
WHERE EmpID = 41;
INSERT TempEmpData
VALUES ('Bill', 'Smith', '11/14/2014', 0, 0, 1, NULL, 2);
SELECT *
FROM TempEmpData
ORDER BY EmpID DESC
END;
错误如下:
Msg 4145, Level 15, State 1, Line 4
An expression of non-boolean type specified in a context where a condition is expected, near 'ID'.Msg 4145, Level 15, State 1, Line 8
An expression of non-boolean type specified in a context where a condition is expected, near 'ID'.Msg 156, Level 15, State 1, Procedure TempEmpDate_INSERT_UPDATE_DELETE, Line 17
Incorrect syntax near the keyword 'TRIGGER'.
如有任何见解,我将不胜感激。
您正在使用“新”内联语法创建函数,太棒了!
第一个错误来自缺少“GO”,将函数的创建与调用分开
CREATE FUNCTION fnInsCosts()
--You function code here
GO
SELECT * FROM dbo.fnInsCosts(2);
你的函数中的第二个错误有它的原因——正如 JamesZ 已经指出的——在错误的分组列中:
SELECT EmpName,
SUM(BaseCost) AS TotBaseCost,
SUM(SpouseIns) AS TotSpouseCost,
SUM(DepIns) AS TotDepCost,
SUM(DentalCost) AS TotDentalCost,
SUM(BaseCost * SpouseIns * DepIns * DentalCost) AS TotInsCost
FROM vwPayroll
WHERE Dependants = @NoDependants
GROUP BY EmpName
你看,唯一没有任何聚合函数的列是 EmpName...
最后一个 - JamesZ 再次声明已经是函数名称中缺少的下划线 OBJECT ID
:
IF OBJECT_ID('TempEmpData') IS NOT NULL
在您的代码中,T-SQL 正在搜索“对象”的含义和名为“ID”的函数...(与 IF OBJECT ID('TempWork') IS NOT NULL
相同)
最后一点:在 SO 上,强烈建议每个问题创建一个问题。这个问题应该至少分为两个单独的问题。想想未来的读者搜索类似的问题...
EDIT Ups,还有一个...
你的最后一条错误消息指向一些代码,我不明白你真正想要实现什么...你是从触发器内部创建触发器吗?可能是,无论如何,MERGE
声明是满足您需求的更好方法...