In my SQL Server 2012 database, I have a table MyTable, a view MyView and a scalar function MyFun.
The view will refer to MyFun as shown below:
CREATE VIEW [dbo].[MyView]
AS
SELECT dbo.MyFun(Age) AS Expr1
FROM dbo.MyTable
While the function will refer to MyView, as shown here:
CREATE FUNCTION [dbo].[MyFun] (#Age int)
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN
SET #Age = (SELECT COUNT(*) FROM [db].[MyView]);
RETURN (#Age + 1);
END;
Since MyFun and MyView will cause circular reference, which one should be created first? I cannot find any documents on this.
I made a test.
First, I export the database as a script. Then I find in the script, the function is created first, as below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[MyFun] (#Age int)
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN
SET #Age = (SELECT COUNT(*) FROM [db].[MyView]);
RETURN(#Age + 1);
END;
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable]
(
[Name] [nchar](10) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[MyView]
AS
SELECT dbo.MyFun(Age) AS Expr1
FROM dbo.MyTable
GO
However, if I modify the script and put function creation after view creation, as below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable]
(
[Name] [nchar](10) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE VIEW [dbo].[MyView]
AS
SELECT dbo.MyFun(Age) AS Expr1
FROM dbo.MyTable
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[MyFun] (#Age int)
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN
SET #Age = (SELECT COUNT(*) FROM [db].[MyView]);
RETURN(#Age + 1);
END;
GO
Then the creation of view will report the following error:
Msg 4121, Level 16, State 1, Procedure MyView, Line 3 [Batch Start Line 17]
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.MyFun", or the name is ambiguous.
So based on the test, for circular reference, the function should be created before the view, and the function can reference objects that have not been created yet.
But how about other objects, such as defaults, triggers, table-valued functions, stored procedures, etc. If they are circular refers to each other, then which one should be created first and which can be created later?
Related
I've got a stored procedure that is coded similarly to the following:
USE [database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[procedure_name]
#record_id int
, #record_value VARCHAR(MAX)
AS
BEGIN
UPDATE dbo.table_1
SET table_1_record_value = #record_value
WHERE table_1_record_int = #record_int
END
BEGIN
INSERT INTO table_2 COLUMNS (table_2_record_id, table_2_record_value) VALUES (#record_id, #record_value)
END
And I'm getting a syntax error. I've never had to write a stored procedure for an application that would accomplish both an UPDATE and an INSERT statement together.
The answer was provided by bbaird in the comments. Removing the BEGIN/END keywords fixed the problem. Thank you!
bbaird's full comment below:
If the procedure isn't created yet, you will need to do CREATE PROCEDURE. 2. The update and insert statements are independent, no need to put them in their own BEGIN...END block unless there is a conditional. 3. COLUMNS in the insert statement might also be throwing things off - it is not necessary so remove it.
The answers of Jake and bbard are correct.
Below the code of your stored procedure:
USE [database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROC [dbo].[procedure_name]
#record_id int
, #record_value VARCHAR(MAX)
AS
BEGIN
UPDATE dbo.table_1
SET table_1_record_value = #record_value
WHERE table_1_record_int = #record_int
INSERT INTO table_2 COLUMNS (table_2_record_id, table_2_record_value)
VALUES (#record_id, #record_value)
END
For documentation of BEGIN and END look here
I have a master table "Repairs" and a detail table "RepairDetails" I am trying to write a procedure to update both tables when I send the appropriate parameters from my application. Here is my SQL:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdateRepair]
#RepairID bigint,
#TypeID bigint = NULL,
#Directions nvarchar(3000) = NULL,
#NewDetails NewDetails READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE Repairs
SET
TypeID = ISNULL(#TypeID, TypeID),
Directions = ISNULL(#Directions, Directions),
LastUpdate = SYSDATETIME()
WHERE RepairID = #RepairID;
IF #NewDetails IS NOT NULL UpdateRepairDetails;
END
where "NewDetails" is a User-defined table type and "UpdateRepairDetails" is a different stored procedure that takes #RepairID and #NewDetails as parameters.
I have an error and a question. The error message is:
Must declare the scalar variable "#NewDetails"
which I don't understand because it is defined.
And my question is: will the parameters "#RepairID" and "#NewDetails" get automatically passed to the "UpdateRepairDetails" procedure. If not, what is the proper approach to accomplish this?
You cannot assign NULL to a table variable. Hence you can't check whether a table variable is NULL.
Second: no. You should call as follows:
EXEC UpdateRepairDetails #RepairID, #NewDetails;
my stored procedure :
USE [maskanjo.com_travelenterDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[SPSelectCites]
-- Add the parameters for the stored procedure here
#cityName nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
--------------------------Select---------------------
CREATE VIEW CUSTOMERS_VIEW AS
SELECT *
FROM [dbo].[City] where [NameFA] LIKE cityName+'%'
-----------------------------------------------------
END
i want select city from cites table and create View
have error
Error :
Incorrect syntax:'CREATE VIEW' Must be only statement in the batch
The error tells you what the problem is. Try executing the query using the "Exec" command:
declare #sql varchar(max)
set #sql = 'CREATE VIEW CUSTOMERS_VIEW AS SELECT * FROM [dbo].[City]
where [NameFA] LIKE ''' + cityName + '%'''
exec (#sql)
Please check my current stored procedure.
USE [CastingDatabase]
GO
/****** Object: StoredProcedure [dbo].[Searching_Talents] Script Date: 11/11/2015 1:41:19 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Searching_Talents]
#name nvarchar(100),
#age_from nvarchar(10),
#age_to nvarchar(10)
AS
BEGIN
SELECT *
FROM [dbo].[Talents]
WHERE(
((#name is null) or (#name='') or ([dbo].[Talents].[Name] LIKE '%'+#name+'%'))
AND
(((#age_to is null) or (#age_to='') or (DATEDIFF(YEAR,Talents.DOB,GETDATE()) IN
(
SELECT CAST (Item as int) FROM dbo.SplitString(#age_to,',')
)
))
)
)
ORDER BY Name
END
I want to add some if_else condition statements in second where clause.
How can I add?
I want to add like this
AND(if(#age_from is null){---- my codes ----})
P.S. I am a newbie in stored procedure. Please help me.
Add CASE where you want to check some value. This doesn't apply only for procedures, it applies on all queries in sql server
...
AND (
CASE
WHEN #age_from IS NULL
THEN yourCode
END
)
or if you have only to check if null and write something else, you can check it like this:
...
AND (ISNULL(#age_from, defaultValue)
and in this case, if value of age_from is null, sql server will put defaultValue which you state in above code.
I do not know if this is a bug.
I found that when this code is run the value in column MyComments is truncated to the first letter. It seems to be related to the declaration of variable #MYComments, cause after I changed the declaration to VARCHAR(MAX) it worked, but what seems to be weird for me is that if no value is set to variable #MYComments function ISNULL(#MYComments, MYComments) invocation should returns the current value.
DECLARE #MYComments AS VARCHAR
UPDATE [dbo].[TestIssue]
SET MYComments = ISNULL(#MYComments,MYComments)
I was able to reproduce this using this script.
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.TestIssue
(
id int NOT NULL,
MYComments varchar(MAX) NOT NULL
) ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE dbo.TestIssue SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
select Has_Perms_By_Name(N'dbo.TestIssue', 'Object', 'ALTER') as ALT_Per, Has_Perms_By_Name(N'dbo.TestIssue', 'Object', 'VIEW DEFINITION') as View_def_Per, Has_Perms_By_Name(N'dbo.TestIssue', 'Object', 'CONTROL') as Contr_Per
INSERT INTO [dbo].[TestIssue]
([id]
,[MYComments])
VALUES
(1
,'MY COMMENT 1')
GO
SELECT * FROM [dbo].[TestIssue]
DECLARE #MYComments AS VARCHAR
UPDATE [dbo].[TestIssue]
SET MYComments = ISNULL(#MYComments,MYComments)
SELECT * FROM [dbo].[TestIssue]
Your problem is with declararion:
Declare #Mycomments VARCHAR
This declaration means that is 1 char long, so return of ISNULL should be also 1 char long. Change declarstion to VARCHAR(MAX). It solve your problem.