T-SQL can't excute my procedure - sql

My code:
CREATE TABLE test (id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
text VARCHAR(255)
);
GO
CREATE PROCEDURE testProc(#string VARCHAR(255))
AS
BEGIN
INSERT INTO test (text) VALUES (#string);
SELECT * FROM test;
END
GO
EXEC testProc('Test01')
The error I get after running it:
Incorrect syntax near 'Test01'.*
I want to insert 'Test01' into my table test with the help of the proc testProc, but it doesn't work.

You just need to omit the parentheses.
EXEC testProc #string = 'Test01';

Related

Cannot return a user table type form a function

I just wrote this coe example to return a user type from a function:
CREATE TYPE dbo.ScheduledActivity_TVP AS TABLE
(
Id uniqueidentifier NOT NULL primary key,
AdditionalDataTypeSignature nvarchar(100) not null,
AdditionalDataId uniqueidentifier NOT NULL,
AdmissionId uniqueidentifier NOT NULL
)
GO
CREATE OR ALTER function [dbo].[Fun_GetFollowUpBymonth](#admissionId uniqueidentifier)
returns ScheduledActivity_TVP as
begin
declare #q ScheduledActivity_TVP
insert into #q
select Id,
AdditionalDataTypeSignature,
AdditionalDataId,
AdmissionId
from ScheduledActivities
where #admissionId = ScheduledActivities.AdmissionId;
return #q
GO
And Sql Server tells me that I must declare the scalar variable #q.
What is wrong in the code above?
I don't see why you are using a multi-line table value function here; they are notoriously slow.
Use an inline table value function, which doesn't even need a TYPE:
CREATE OR ALTER FUNCTION [dbo].[Fun_GetFollowUpBymonth] (#admissionId uniqueidentifier)
RETURNS table
AS RETURN
SELECT Id,
AdditionalDataTypeSignature,
AdditionalDataId,
AdmissionId
FROM dbo.ScheduledActivities
WHERE #admissionId = ScheduledActivities.AdmissionId;

Atomically INSERT+SELECT or SELECT row (based on UNIQUE column)

My table is created as follows:
CREATE TABLE StackFunctionID
(
m_FunctionID int PRIMARY KEY IDENTITY,
m_GroupID int DEFAULT 0 NOT NULL,
m_Function varchar(256) UNIQUE NOT NULL,
);
GO
CREATE TRIGGER INSERT_MakeGroupID ON StackFunctionID AFTER INSERT AS
BEGIN
SET NOCOUNT ON;
UPDATE StackFunctionID
SET StackFunctionID.m_GroupID = INSERTED.m_FunctionID
FROM StackFunctionID
INNER JOIN INSERTED ON (StackFunctionID.m_FunctionID = INSERTED.m_FunctionID)
END;
Now I'm trying to write a query for Sql Server 2008 that will
If m_Function does not exist, create it, and return m_FunctionID, m_GroupID
If m_Function exists, return m_FunctionID, m_GroupID
Perform it atomically
After much trying, this is what worked for the last years:
DECLARE #Results TABLE(m_FunctionID INT, m_GroupID INT); -- trash use
DECLARE #dummy1 int; -- trash use
MERGE INTO StackFunctionID WITH(HOLDLOCK) AS Target -- WITH(HOLDLOCK) for thread safety
USING (VALUES(null)) AS dummy2(dummy3) -- syntax requires USING
ON Target.m_Function = #m_Function
WHEN MATCHED THEN
UPDATE SET #dummy1 = 0 -- syntax requires something in 'WHEN MATCHED', which is needed for OUTPUT
WHEN NOT MATCHED THEN
INSERT(m_Function) VALUES(#m_Function)
OUTPUT inserted.m_FunctionID, inserted.m_GroupID
INTO #Results; -- Having a trigger requires 'INTO'
SELECT * FROM #Results -- Having a trigger requires 'INTO'
However, there was a bug: when a row is INSERTED, OUTPUT returns m_GroupID=0
Questions:
How do I always get correct m_GroupID ?
Is it possible to achieve the goal with a simpler query? (because current one is really hard to understand with all those "syntax requirements")
Relying on UNIQUE m_Function use TRY CATCH to INSERT and then SELECT.
Demo
CREATE TABLE StackFunctionID
(
m_FunctionID int PRIMARY KEY IDENTITY,
m_GroupID int DEFAULT 0 NOT NULL,
m_Function varchar(256) UNIQUE NOT NULL,
);
INSERT StackFunctionID(m_Function)
VALUES ('a'), ('b');
SELECT * FROM StackFunctionID;
DECLARE #m_Function varchar(256) = 'a';
BEGIN TRY
INSERT StackFunctionID(m_Function)
VALUES ( #m_Function);
END TRY
BEGIN CATCH
PRINT 'Already exists';
END CATCH
SELECT m_FunctionID, m_GroupID
FROM StackFunctionID
WHERE m_Function = #m_Function;

How can I pass tables to stored procedures?

I have a table of data like this, and one procedure is going to populate data in it like this,
DECLARE #ClaimChanges TABLE (
ChangeType NVARCHAR(10)
,contract_id int NOT NULL
,dispatch_id int NOT NULL
,dispatch_claim_id int NOT NULL
,item_no VARCHAR(100) NULL
,old_units VARCHAR(100) NULL
);
I would then like to pass that data to a different stored procedure which would be defined like this,
CREATE procedure [dbo].[ct_audit_oncost](
#table TABLE readonly,
#OutValue nvarchar(255) = null output
)
as
-- some stuff
go
I gather this is not possible as I am getting an error,
Incorrect syntax near the keyword 'TABLE'.
Table valued parameters are supported since 2008 version.
However, you can't just pass any table you want, first you need to define a user defined table type:
CREATE TYPE dbo.MyUDT as TABLE
(
ChangeType NVARCHAR(10)
,contract_id int NOT NULL
,dispatch_id int NOT NULL
,dispatch_claim_id int NOT NULL
,item_no VARCHAR(100) NULL
,old_units VARCHAR(100) NULL
)
Then you can use it in your stored procedure:
CREATE procedure [dbo].[ct_audit_oncost]
(
#table dbo.MyUDT readonly,
#OutValue nvarchar(255) = null output
)
as
-- some stuff
go
Please note you should also use it to declare the table to send to the database:
DECLARE #Out nvarchar(255)
DECLARE #ClaimChanges as dbo.MyUdt
INSERT INTO #ClaimChanges (ColumnsList) VALUES (ValuesList)
EXEC ct_audit_oncost #ClaimChanges, #Out output

Searching a table using a user-defined function

I'm trying to write an SQL function that given a name of a game, it will allow me to search the table of games for that particular game and returns all the info about that game.
This is the code for the Games table:
CREATE TABLE Games(
game_id INT IDENTITY PRIMARY KEY,
name VARCHAR(50),
release_date VARCHAR(50),
rating VARCHAR(5),
min_age INT,
development_team_email VARCHAR(50) FOREIGN KEY REFERENCES Development_Teams,
release_conference INT FOREIGN KEY REFERENCES Conferences
)
And here is the what I could come up with when I was trying to write the function:
create function SearchGames(#game_name varchar(50))
returns table
begin
declare #game
Select (*)
From Games
where Games.name = #game_name
return #game
end
I'm getting a lot of syntax errors and I don't know what I'm doing wrong. Any help appreciated.
Use inline table valued function syntax and add schema:
create function dbo.SearchGames(#game_name varchar(50))
returns table
AS
RETURN (Select *
From Games
where Games.name = #game_name);
SqlFiddleDemo
If you use stored procedure you need to use:
CREATE TABLE ...;
INSERT INTO ... EXEC stored_procedure #args;
-- another operation on stored procedure resultset
while with inline table function you just:
SELECT * FROM dbo.SearchGames('aaa') GROUP BY ... HAVING ... ORDER BY;
I wouldn't recommend using a function for this, but rather a stored procedure:
Create Proc spSearchGames (#game_name Varchar (50))
As Begin
Select *
From Games
Where name = #game_name
End
Go
And executing it:
Exec spSearchGames 'YourGameName'

Deletion\Creation of Temp tables in SQL Server 2008

I have SQL code like this
IF Object_id('tempdb..#empDate) IS NOT NULL
DROP TABLE #empDate
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
After the above code some more lines of SQL follow and then it is repeated.
I get the following error.
Msg 2714, Level 16, State 1, Line 589
There is already an object named '#empDate' in the database.
I replaced the
IF Object_id('tempdb..#empDate) IS NOT NULL
with
IF Object_id('tempdb..#empDate%) IS NOT NULL
As it is written on the forums that SQL Server appends number to the subsequent temp table(s).
Source:
Check if a temporary table exists and delete if it exists before creating a temporary table
http://blog.sqlauthority.com/2009/05/17/sql-server-how-to-drop-temp-table-check-existence-of-temp-table/
http://blog.sqlauthority.com/2009/03/29/sql-server-fix-error-msg-2714-level-16-state-6-there-is-already-an-object-named-temp-in-the-database/
I am using Microsoft SQL Server 2008 on Windows 7 Enterprise.
I am not able to understand the cause of the error.
Please help.
Sample One
This will fail......
Executing the same code again, will throw the error you are getting now
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
Sample Two (Fixed)
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
GO --<-- Adding this Batch Separator will eliminate the Error
IF Object_id('tempdb..#empDate') IS NOT NULL
BEGIN
DROP TABLE #empDate
END
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
Test
If you try Executing the following Statements in ONE BATCH they will fail even though there isnt any table at all with the name #empDate, it will not even execute the very 1st Create table Statement. and will throw an error.
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
DROP TABLE #empDate
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
But if you separate all the statement in separate batches they will be executed successfully something like this..
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
GO
DROP TABLE #empDate
GO
CREATE TABLE #empDate
(
[empID] INT,
[AddLoc] VARCHAR(1000)
)
GO
I would just drop your table without any pre-checks.
Then write/run the script clean.
Once done using the temp table, drop it at the end of your script.
So run this unconditionally
DROP TABLE #empDate
Then write/run your script and make sure you have this line at the end of your script.
pass database name with object_id
example :
DECLARE #db_id int;
DECLARE #object_id int;
SET #db_id = DB_ID(N'AdventureWorks2012');
SET #object_id = OBJECT_ID(N'AdventureWorks2012.Person.Address');
IF #db_id IS NULL
BEGIN;
PRINT N'Invalid database';
END;
ELSE IF #object_id IS NULL
BEGIN;
PRINT N'Invalid object';
END;
ELSE
BEGIN;
SELECT * FROM sys.dm_db_index_operational_stats(#db_id, #object_id, NULL, NULL);
END;
GO