Creating only one table in a stored procedure - sql

Is it possible to create a table only once while executing the same procedure several times eg:
create procedure grg
(#firstname varchar(100),
#lastname varchar(100),
#dob date,
#loginID varchar(100),
#password varchar(100),
#email varchar(100),
#SSN varchar(11)
)
as
begin
create table............ <- only once
select
#firstname, #lastname,
#dob, #loginID, #password, #email,
#SSN
If(.....)

you can use CREATE TABLE IF NOT EXISTS
Keep in mind the if the table already exists it will show a warning not an error.
You can ignore the warning. If you want to temporarily disable the warning you can do it as follows.
SET sql_notes = 0;
CREATE TABLE IF NOT EXISTS
SET sql_notes = 1;

Yeah with sql you can use temp tables just prefix them with a hash.
#
These tables would only exist on the current session
If you really want the stored proc to handle the creation of the table then you can create the table on the stored procedure's definition. Just make sure to validate if table already exists so you don't get errors.
CREATE PROCEDURE XX
AS
BEGIN
IF EXISTS (SELECT * FROM sysobjects WHERE name = <table_name>)
BEGIN
<---INSERT CREATE TABLE SCRIPT HERE---->
END
<---POPULATE HERE--->
END

Try following
CREATE PROCEDURE grg
(#firstname VARCHAR(100),
#lastname VARCHAR(100),
#dob DATE,
#loginID VARCHAR(100),
#password VARCHAR(100),
#email VARCHAR(100),
#SSN VARCHAR(11)
)
AS
BEGIN
IF NOT EXISTS
(
SELECT * FROM sysobjects WHERE name = 'myTable' AND xtype = 'U'
)
BEGIN
CREATE TABLE myTable(Name VARCHAR(64) NOT NULL);
END;
SELECT * FROM myTable;
END;

Related

How to call an insert stored procedure during another insert stored procedure and get its returned ID?

My apologies if my question doesn't make sense.
So I have taken a database table that uses GUID's as the PK's and I have normalized this database and am starting to merge the data from the existing database to the newly structured database.
I have an originating table that looks like this
create table #tmpMaterial
(
ID int identity(1,1),
MaterialID nvarchar(128),
MaterialCategoryID nvarchar(128),
MaterialTypeID nvarchar(128),
MaterialSubTypeID nvarchar(128),
MaterialDetail nvarchar(20),
Description nvarchar(100),
MaterialWidth numeric(10,2),
MaterialLength int,
MaterialSize nvarchar(20),
PurchUnitOfMeasureID nvarchar(128),
PurchaseItemQuantity int,
SellUnitOfMeasureID nvarchar(128),
SellItemQuantity int,
NewPrice money,
RemodPrice money,
ServicePrice money,
DefVendorID nvarchar(128),
EnabledInd tinyint
)
and the inserting of the data is this
insert into #tmpMaterial
select tmpM.MaterialID, tmpM.MaterialCategoryID,tmpM.MaterialTypeID, tmpM.MaterialSubTypeID, tmpM.MaterialDetail, tmpM.Description, tmpM.MaterialWidth, tmpM.MaterialLength, tmpM.MaterialSize,
tmpM.PurchUnitOfMeasureID, tmpM.PurchItemQuantity, tmpM.SellUnitOfMeasureID, tmpM.SellItemQuantity, tmpM.NewPrice, tmpM.RemodPrice, tmpM.ServicePrice, tmpM.DefVendorID, tmpM.EnabledInd
from Exovations.dbo.Material tmpM
So this inserts the original data into the temp table, this temp table is what I am querying against.
I have a temp table which is the exact newly created table and it is
create table #tmpMaterialFinal
(
ID int identity(1,1),
MaterialCategoryID int,
MaterialTypeID int,
MaterialSubTypeID int,
CompanyID int,
DimensionsID int,
PurchaseUOMID int,
SellUOMID int,
VendorID int,
MaterialDetail nvarchar(20),
Description nvarchar(100),
PurchaseItemQuantity int,
NewPrice money,
RemodelPrice money,
ServicePrice money,
IsActive bit
)
I am querying the #tmpMaterial table and doing some joins in the process to import that data into the #tmpMaterialFinal table. Where I am forseeing an issue is if you take a look at the #tmpMaterial table I have these three columns
MaterialWidth numeric(10,2),
MaterialLength int,
MaterialSize nvarchar(20)
and in my #tmpMaterialFinal I have DimensionsID, which is its own table called Dimensions, in the Dimensions table I have 3 columns, one for Width, Length and Size.
What I need to do is while inserting records into the #tmpMaterialFinal table I need to call a stored procedure called usp_InsertDimensions and pass those 3 values from the #tmpMaterial table and while inserting into the #tmpMaterialFinal table I need to execute the usp_InsertDimensions stored procedure and get its returned ID so I can place that ID into the DimensionsID column.
my usp_InsertDimensions looks like this
CREATE PROCEDURE [dbo].[usp_InsertDimensions]
(
#DimensionID int output,
#DLength decimal(15,4),
#DWidth decimal(15,4),
#DHeight decimal(15,4)
)
AS
SET NOCOUNT OFF
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
DECLARE #ERROR_SEVERITY int,
#MESSAGE varchar(1000),
#ERROR_NUMBER int,
#ERROR_PROCEDURE nvarchar(200),
#ERROR_LINE int,
#ERROR_MESSAGE nvarchar(4000);
begin try
insert into [Dimensions]
(DLength, DWidth, DHeight)
values
(#DLength, #DWidth, #DHeight)
set #DimensionID = SCOPE_IDENTITY()
end try
BEGIN CATCH
SET #ERROR_SEVERITY = ISNULL(ERROR_SEVERITY(),'');
SET #ERROR_NUMBER = ISNULL(ERROR_NUMBER(),'');
SET #ERROR_PROCEDURE = ISNULL(ERROR_PROCEDURE(),'');
SET #ERROR_LINE = ISNULL(ERROR_LINE(),'');
SET #ERROR_MESSAGE = ISNULL(ERROR_MESSAGE(),'');
-- Test if the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
--PRINT N'The transaction is in an uncommittable state. Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
-- Test if the transaction is active and valid.
IF (XACT_STATE()) = 1
BEGIN
--PRINT N'The transaction is committable. Committing transaction.'
COMMIT TRANSACTION;
END;
SET #MESSAGE = 'Error Occured in Stored Procedure ' + cast(#ERROR_PROCEDURE as varchar(200)) +
'; Line Number ' + cast(#ERROR_LINE as varchar) +
'; Message: [' + cast(#ERROR_NUMBER as varchar) + '] - '
+ cast(#ERROR_MESSAGE as varchar(255))
RAISERROR(#MESSAGE, #ERROR_SEVERITY, 1);
END CATCH;
Any ideas on the correct way to achieve this?
Here's one approach you could use:
Add a DimensionId field on your first table #tmpMaterial
Generate sql statements to insert dimensions into Dimensions table and store the DimensionId back onto the #tmpMaterial table. Something like this should work (don't have MSSQL at hand to test at the moment):
select 'declare #d_id int; exec usp_InsertDimensions #d_id output, ' + cast(MaterialLength as varchar(100)) + ', ' + cast(MaterialWidth as varchar(100)) + ', ' + cast(MaterialSize as varchar(100)) + '; Update #tmpMaterial set DimensionId = #d_id where ID = ' + cast(ID as varchar(100)) + '; go;'
from #tmpMaterial
This will give you all the statements required to insert the dimensions and store their ids back in your source table. You could also concatenate all these statements in a variable and then execute them as dynamic sql, or store the statements in a temp table and execute in batches.
From here on, the insert into the final table would be straightforward.

SQL: How to make table name in stored procedure dynamic

I am pretty new to SQL Server and hope someone here can help me with this (I'm using QL Server 2008).
The following is a small procedure that works as intended.
Now I would like to use the same procedure to update multiple tables as all these tables have exactly the same column names and column formatting, the only difference is the 2nd part of the table name for which I added XXX below.
Can someone tell me how this could be made dynamic and also provide me some explanations on this ?
I cannot provide much more here as I wasn't sure about how to approach this - other than probably declaring #sql nvarchar(max) and wrapping the whole query in SET #sql = N'...' before executing it.
My stored procedure:
CREATE PROCEDURE [dbo].[Cal_UpdateTeam]
#team nvarchar(100),
#teamID int,
#notes nvarchar(1000),
#log nvarchar(100),
#admin varchar(50)
AS
BEGIN
SET NOCOUNT ON;
BEGIN
IF NOT EXISTS
(
SELECT *
FROM Cal_XXX
WHERE teamID = #teamID
)
INSERT INTO Cal_XXX
(
team,
teamID,
notes,
log,
admin
)
SELECT #team,
#teamID,
#notes,
#log,
#admin
ELSE
UPDATE Cal_XXX
SET team = #team,
teamID = #teamID,
notes = #notes,
log = #log,
admin = #admin
WHERE teamID = #teamID
END
END
Many thanks for any tips and advise on this, Mike.
you should wrap your sql query in an nvarchar and then execute that query as in the below example :
declare #sql nvarchar(max)
declare #TableName nvarchar(max)
set #TableName = 'mytable'
set #sql = 'Select * from ' + #TableName
Exec sp_executesql #sql
in SP you can use Temporary Tables fro example:
CREATE PROCEDURE SELECT_TABLE
#REQUEST_ID INT
AS
BEGIN
/*************************************
** Temporary table **
*************************************/
CREATE TABLE #SOURCE (
ID INT
, ID_PARENT INT
, NAME VARCHAR(200)
, SORT INT
..
..
)
IF #REQUEST_ID = 'YES' BEGIN
INSERT INTO #SOURCE SELECT * FROM SOURCE_A
END
ELSE BEGIN
INSERT INTO #SOURCE SELECT * FROM SOURCE_B
END
SELECT * FROM #SOURCE
.....
END
GO
in SP you can encapsulate other SPs with different table names like parameter:
CREATE PROCEDURE SELECT_FROM_TABLE_A
AS
BEGIN
SELECT * FROM SOURCE_A
END
GO
CREATE PROCEDURE SELECT_FROM_TABLE_B
AS
BEGIN
SELECT * FROM SOURCE_B
END
GO
CREATE PROCEDURE SELECT_TABLE
#REQUEST_ID INT
AS
BEGIN
/**********************************************
** Subrequest select **
**********************************************/
IF #REQUEST_ID = 'YES' BEGIN
-- Request SP fro Source A
EXEC SELECT_FROM_TABLE_A
END
ELSE
BEGIN
-- Request SP fro Source B
EXEC SELECT_FROM_TABLE_B
END
END
GO

Search ID, first name and last name in SQL using Like

Hi I have this stored procedure for Searching employee information. I want the user to have the choice to enter ID, or First Name or Last Name. but when I execute this stored procedure, it requires the other parameters.
create proc searchtry
#empID int,
#firstname varchar(20),
#lastname varchar(20)
as
begin
select fld_EmployeeId,fld_EmployeeFirstName,fld_EmployeeLastName
from Reference.tbl_EmployeeDetails
where fld_EmployeeId like #empID
OR fld_EmployeeFirstName like #firstname
OR fld_EmployeeLastName like #lastname
end
You should give default values to the parameters
create proc searchtry
#empID int = NULL,
#firstname varchar(20) = '',
#lastname varchar(20) = ''
as
begin
select fld_EmployeeId,fld_EmployeeFirstName,fld_EmployeeLastName
from Reference.tbl_EmployeeDetails
where fld_EmployeeId like #empID
OR fld_EmployeeFirstName like #firstname
OR fld_EmployeeLastName like #lastname
end

Trigger to update table according to user rank

I'm a stranger to SQL Server Triggers.
I ended up having a problem like this. Please have a look.
I have two tables 'users' & 'test'
CREATE TABLE users(
email VARCHAR(250),
rank FLOAT
);
CREATE TABLE test(
score INT,
total INT
);
I need to create a trigger to;
2.1 Update users rank by the value of avg ( avg = test.score / test.total)
2.2 Here's What I tried so far:
CREATE TRIGGER auto_rank ON dbo.test FOR INSERT
BEGIN
DECLARE #sc INT
DECLARE #tot INT
DECLARE #avg FLOAT
#tot = SELECT inserted.total FROM dbo.test
#sc = SELECT inserted.score FROM dbo.test
SET #avg=#sc/#tot
UPDATE dbo.users SET rank=#avg WHERE email=inserted.email
END
You missing the email in test from your table design, but it should have such column per your code:
UPDATE dbo.users SET rank=#avg WHERE email=inserted.email
Then you need a view instead of trigger in this case:
Create view user as (select email, score/total as rank from test group by email);
Hope this help.
Try this :
CREATE TRIGGER auto_rank ON dbo.test FOR INSERT
BEGIN
UPDATE a SET a.rank=b.rn
from
users a
inner join
(select email,inserted.score/inserted.total rn from inserted)b
on a.email=b.email
END
I have not tested this, but this should work fine.
You need to modify your tables so that the test table contains the email column:
CREATE TABLE test(score INT,
total INT,
email varchar(250)
);
Then you can create the trgiger like this:
CREATE TRIGGER [dbo].[auto_rank] ON [dbo].[test]
FOR INSERT
AS
BEGIN
DECLARE MyCursor CURSOR FOR
SELECT score, total, email FROM Inserted
DECLARE #sc INT
DECLARE #tot INT
DECLARE #email VARCHAR(30)
DECLARE #avg FLOAT
DECLARE #MSG VARCHAR(50)
OPEN MyCursor;
FETCH NEXT FROM MyCursor INTO #sc, #tot, #email
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #avg=#sc/#tot
UPDATE users SET rank=#avg WHERE users.email=#email
SELECT #MSG = 'email Updated ' + #email + '. New Rank is ' + Str(#avg, 25, 5);
PRINT #MSG
FETCH NEXT FROM MyCursor
END;
CLOSE MyCursor;
DEALLOCATE MyCursor;
END
Sorry for being so late to continue this thread but, I'm happy to say that I found the answer. it's because of you all.
So, here's what i did;
first;
CREATE TABLE users(
email VARCHAR(250),
rank FLOAT,
constraint pk_users PRIMARY KEY(email)
);
CREATE TABLE test(
email VARCHAR(250),
score INT,
total INT,
constraint pk_test PRIMARY KEY(email),
constraint fk_from_users FOREIGN KEY(email) references users(email)
);
create trigger trig_ex02 on dbo.test
after insert
as
begin
declare #score FLOAT
declare #total FLOAT
declare #average FLOAT
declare #msg varchar(100)
declare #email varchar(250)
set #email = (select email from inserted)
set #score = (select score from inserted)
set #total = (select total from inserted)
set #average =(#score/#total)
select #msg = 'SCORE IS'+ str(#score)+'TOTAL IS'+str(#total)+' AVERAGE IS ' +str(#average,25,5)+' END '
print #msg
UPDATE users SET rank=#average WHERE users.email=#email
end;

SQL Server: Return uniqueidentifier from stored procedure

Can I return UNIQUEIDENTIFIER from a stored procedure using the RETURN statement or is it only by using the OUTPUT statement?
i.e to return the PersonID UNIQUEIDENTIFIER:
CREATE PROCEDURE CreatePerson
#Name NVARCHAR(255),
#Desc TEXT
AS
DECLARE #Count INT
DECLARE #JobFileGUID UNIQUEIDENTIFIER
-- Check if job exists?
SET #Count = (SELECT COUNT(Name) AS Name FROM Person WHERE Name=#Name)
IF #Count < 1
BEGIN
SET #PersonGUID = NEWID();
INSERT INTO Person
(PersonID, Name, [Desc])
VALUES (#PersonGUID, #Name, #Desc)
END
SELECT #PersonGUID = Person.PersonID
FROM Person
WHERE Name = #Name
RETURN #PersonGUID
GO
Thanks
In stored procedure - only using the OUTPUT statement. In function - return.
Use:
CREATE PROCEDURE CreatePerson
#Name NVARCHAR(255),
#Desc TEXT,
#PersonGUID UNIQUEIDENTIFIER OUTPUT
AS
BEGIN
SET #PersonGUID = ...
END
How to call:
DECLARE
#name NVARCHAR(255),
#desc TEXT,
#personGUID UNIQUEIDENTIFIER
SET #name = 'Bob'
SET #desc = 'One handsome man.'
EXEC [Database].[schema].CreatePerson #name, #desc, #personGUID OUTPUT
From the documentation you can actually see that a return in a stored procedure is actually used as a response code, hence you get the exception when trying to return a uniqueidentifier.
https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/return-data-from-a-stored-procedure?view=sql-server-ver16#return-data-using-a-return-code
How I solved it, is by just performing a SELECT after the insert of the generated unique identifier.
DECLARE #ReportId UNIQUEIDENTIFIER;
SET #ReportId = NEWID();
INSERT INTO [dbo].[Report]
([ReportId]
,[ReportName])
VALUES
(#ReportId
,#ReportName)
SELECT #ReportId as ReportIdInternal
You'll have to see how to perform that with multiple selects though.
CREATE TABLE [dbo].[tbl_Clients]( [ClientID] [uniqueidentifier] NULL, [ClientName] varchar NULL, [ClientEnabled] [bit] NULL ) ON [PRIMARY]
GO
CREATE PROCEDURE [dbo].[sp_ClientCreate] #in_ClientName varchar(250) = "New Client 123", #in_ClientEnabled bit, #out_ClientId uniqueidentifier OUTPUT AS
SET #out_ClientId = NEWID();
INSERT INTO tbl_Clients(ClientId, ClientName, ClientEnabled) VALUES( #out_ClientId, #in_ClientName, #in_ClientEnabled)
DECLARE #return_value int, #out_ClientId uniqueidentifier
EXEC #return_value = [dbo].[sp_ClientCreate] #in_ClientName = N'111', #in_ClientEnabled = 1, #out_ClientId = #out_ClientId OUTPUT
SELECT #out_ClientId as N'#out_ClientId'
SELECT 'Return Value' = #return_value
GO
Result:-59A6D7FE-8C9A-4ED3-8FC6-31A989CCC8DB