Can't drop a view inside a function - sql

I'm trying to make a simple function to return a random eye color. I could do this in a stored procedure but I was trying to challenge my self and try something new. I'm getting some errors, I've tried this a few different ways and I have found some documents roughly related but I'm just not skilled enough I think to understand what I did wrong and what the documents I've found are referring too syntax wise. I hope that makes sense.
CREATE FUNCTION Random_Eyes ()
RETURNS NVARCHAR(100)
AS
BEGIN
CREATE VIEW Rand_Eyes
AS
SELECT TOP 1 [Eyes]
FROM [dbo].[Eyes]
ORDER BY NEWID()
GO
DECLARE #Eyes AS NVARCHAR(100) = (SELECT [Eyes] FROM Rand_Eyes)
RETURN #Eyes
DROP VIEW Rand_Eyes
END
GO
Errors:
Msg 156, Level 15, State 1, Procedure Random_Eyes, Line 14
Incorrect syntax near the keyword 'VIEW'.
Msg 102, Level 15, State 1, Procedure Random_Eyes, Line 14
Incorrect syntax near ')'
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near 'END'.
Any feedback or suggestions would be helpful. Thank you

You don't need a temporary view inside a function - that's not even allowed anyway as functions in SQL Server are strictly read-only: they cannot perform any DDL operations (CREATE, UPDATE, INSERT, DELETE).
Note that ORDER BY NEWID() is not the best way to get a random result (because it triggers a table linear scan). Try this:
CREATE FUNCTION Random_Eyes()
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE #count int = ( SELECT COUNT(*) FROM [Eyes] )
SELECT
Eyes
FROM
dbo.Eyes
ORDER BY
EyeId -- or whatever your constant, incrementing primary-key is
OFFSET
( RAND() * #count ) ROWS
FETCH NEXT
1 ROWS ONLY
END

Related

Msg 178, Level 15, State 1, Line 8 A RETURN statement with a return value cannot be used in this context

I received this error message while trying to execute below SQL.
Error:
Msg 156, Level 15, State 1, Line 5
Incorrect syntax near the keyword 'FUNCTION'.
Msg 178, Level 15, State 1, Line 8
A RETURN statement with a return value cannot be used in this context.
SQL:
IF (NOT EXISTS (SELECT * FROM DBO.TRACKING WHERE CR = 123))
BEGIN
CREATE FUNCTION [dbo].[UDFDate]()
RETURNS DATETIME
AS BEGIN
RETURN CAST('9999-12-31' AS DATETIME)
END
END
Am I not allowed to create a Function inside if statement ?
There are no reasons why you would want to create functions inside a stored procedure during runtime. Functions in SQL SERVER work similarly to stored procedures, so if you want to create a function you need to do it outside of the context and scope of a stored procedure and it will be saved on your database to be accessed at any time.
Ontopic, if you only want to exhibit that date value you could just remove the function creation and select the datetime result as this:
IF (NOT EXISTS (SELECT TOP 1 1 FROM DBO.TRACKING WHERE CR = 123))
BEGIN
SELECT CAST('9999-12-31' AS DATETIME)
END
PS: Don't use "SELECT *" when you just want to know if some value exists. It creates unnecessary overhead to bring all columns when you just want to know if anything exists.
You cannot create a function inside an if statment this way you will get the following warning
Incorrect syntax: CREATE FUNCTION must be the only statment in the batch
you can do it by creating a variable stor the create query in this variable and execute it:
IF (NOT EXISTS (SELECT * FROM DBO.TRACKING WHERE CR = 123))
BEGIN
DECLARE #strQuery AS VARCHAR(MAX)
SET #strQuery = '
CREATE FUNCTION [dbo].[UDFDate]()
RETURNS DATETIME
AS BEGIN
RETURN CAST(''9999-12-31'' AS DATETIME)
END
'
EXEC(#strQuery)
END
but i didn't understand why creating a function to return a static value??!!

Create trigger error: 'Incorrect Syntax near 'dbo'

I'm currently learning some regarding SQL triggers. I am trying to create a column on a test table which will show the current date when the row is updated. The column datatype is type DateTime So far I have:
CREATE TRIGGER lastUpdated
ON [dbo].[ImportTest]
AFTER UPDATE
AS
BEGIN
IF NOT UPDATE(LAST_UPD)
BEGIN
SET [dbo].[ImportTest].[LAST_UPD] = CURRENT_TIMESTAMP
END
END
GO
However, I get the following error trying to execute:
Msg 102, Level 15, State 1, Procedure lastUpdated, Line 29
Incorrect syntax near 'dbo'.
Any help would be appreciated.
You cannot update a column like assigning value to variable. Try this
IF NOT UPDATE(LAST_UPD)
BEGIN
UPDATE IT
SET [LAST_UPD] = CURRENT_TIMESTAMP
FROM [dbo].[ImportTest] IT
WHERE EXISTS (SELECT 1
FROM inserted i
WHERE i.somecol = it.somecol
And ...)
END

Why would I get a syntax error on this pretty simple trigger?

I'm getting a syntax error :
Msg 156, Level 15, State 1, Procedure trgDiscoverSurchargeChangeTiming, Line 26
Incorrect syntax near the keyword 'select'
on a trigger I'm writing. Now, I normally avoid triggers because I tend to forget them later when I am making changes to the DB, so I'm a little rusty on them, but I feel like this one should be fine:
(TRIGGER STUFF)Begin
if update(surchargepay)
begin
insert into
dbo.CustomErrorLog
(errorText
, ErrorOrderID
, errorOldValue
, errorNewValue)
values
select -- This is where the error is being thrown
convert(varchar(50), getdate())
, i.routeid
, d.surchargepay
, i.surchargepay
from
inserted i INNER JOIN
deleted d on i.id = d.id
end
End
any ideas what might cause that?
You don't need the "value" keyword when using "select" to populate an insert.

Need to create triggers for audit tracking, getting "incorrect syntax?"

I have one table Products on which i need to create trigger to update changes (new data) in data in another table Products_audit which has same columns with same data.
I've tried following:
CREATE TRIGGER Super
ON Products
AFTER INSERT, UPDATE
AS
UPDATE Product_audit (Column1,Column2, Column3, ... )
SELECT (Column1,Column2,Column3,...)
FROM Products
Receiving the following error:
Server: Msg 170, Level 15, State 31, Procedure Super, Line 20
Line 20: Incorrect syntax near '('.
Server: Msg 170, Level 15, State 1, Procedure Super, Line 24
Line 24: Incorrect syntax near ','.
I use sql server 2000
I'm not so strong else in triggers creation could you please correct me I'd like to know where was I wrong ?
I think you trigger need to look like this:
CREATE TRIGGER Super
ON Products
AFTER INSERT, UPDATE
AS
UPDATE Product_audit
SET Column1 = p.Column1
SET Column2 = p.Column2
FROM Products p
Hello you have to create two different trigger one for update and one for insert
1) For Insert
CREATE TRIGGER Super
ON Products
AFTER INSERT
AS
BEGIN
INSERT INTO Product_audit
(Column1,Column2,...)
SELECT Column1,Column2,...
FROM Inserted
END
2) For Update
CREATE TRIGGER Super
ON Products
AFTER Update
AS
BEGIN
DECLARE #Column1 as varchar(10)
DECLARE #Column2 as varchar(10)
DECLARE #ID INT
SELECT #ID=ID,#Column1=Column1,#Column2=Column2 FROM INSERTED
UPDATE Product_audit SET Column1=#Column1,Column2=#Column2
WHERE ID=#ID
END

Stored Procedure consist Add column, Update data for that column, and Select all data from that table

I've written a stored procedure as following:
CREATE PROC spSoNguoiThan
#SNT int
AS
begin
IF not exists (select column_name from INFORMATION_SCHEMA.columns where
table_name = 'NhanVien' and column_name = 'SoNguoiThan')
ALTER TABLE NhanVien ADD SoNguoiThan int
else
begin
UPDATE NhanVien
SET NhanVien.SoNguoiThan = (SELECT Count(MaNguoiThan)FROM NguoiThan
WHERE MaNV=NhanVien.MaNV
GROUP BY NhanVien.MaNV)
end
SELECT *
FROM NhanVien
WHERE SoNguoiThan>#SNT
end
GO
Then I get the error :
Server: Msg 207, Level 16, State 1, Procedure spSoNguoiThan, Line 12
Invalid column name 'SoNguoiThan'.
Server: Msg 207, Level 16, State 1, Procedure spSoNguoiThan, Line 15
Invalid column name 'SoNguoiThan'.
Who can help me?
Thanks!
When the stored proc is parsed during CREATE the column does not exist so you get an error.
Running the internal code line by line works because they are separate. The 2nd batch (UPDATE) runs because the column exists.
The only way around this would be to use dynamic SQL for the update and select so it's not parsed until EXECUTE time (not CREATE time like now).
However, this is something I really would not do: DDL and DML in the same bit of code
I ran into this same issue and found that in addition to using dynamic sql I could solve it by cross joining to a temp table that had only one row. That caused the script compiler to not try to resolve the renamed column at compile time. Below is an example of what I did to solve the issue without using dynamic SQL
select '1' as SomeText into #dummytable
update q set q.ValueTXT = convert(varchar(255), q.ValueTXTTMP) from [dbo].[SomeImportantTable] q cross join #dummytable p