Error Using Temporary Tables With Same Names SQL Server - sql

Here is my scenario. (Following is my stored proc taking #date as an input parameter)
DECLARE #date DATE
If object_id('tempdb..#TempList') is not null drop table #TempList
go
Create table #TempList (MILL_NO VARCHAR(7), SHIP_DATE DATE, BL_STATUS NCHAR(1),
FOOTAGE DECIMAL(12,4))
If #date IS NULL
Insert into #TempList
Select mill_no, null, bl_status,footage from fn_A(0,0)
Select * from #TempList
If object_id('tempdb..#TempList') is not null drop table #TempList
go
Create Table #TempList (MILL_NO VARCHAR(7), SHIP_DATE DATE, BL_STATUS NCHAR(1),
FOOTAGE DECIMAL(12,4))
If #date IS NOT NULL
Insert into #TempList
Select * from fn_B(0,'06/06/2006')
Select * from #TempList
I figured out from one of the posts that I cannot use temporary tables with same names unless I inclide a GO. However, including GO is not taking the parameters I try to pass.
Is there an alternate approach to eliminate this error?

Based on the procedure supplied, you could use TRUNCATE TABLE instead.
I don't see a point dropping and recreating a table if all you want to do is quickly remove the records.
EDIT
You don't drop and recreate your table with the same name; instead of this code:
If object_id('tempdb..#TempList') is not null drop table #TempList go
Create Table #TempList (
MILL_NO VARCHAR(7),
SHIP_DATE DATE,
BL_STATUS NCHAR(1),
FOOTAGE DECIMAL(12,4)
)
Just do this:
TRUNCATE TABLE #TempList

if object_id('tempdb..#TempList') is allways NULL because #TempList is not the name that results created on tempdb's sysobjects table when you do create table #TempList
EDIT
what about this:
CREATE PROC PIRULO(#date as DATE) as
Create table #TempList (MILL_NO VARCHAR(7), SHIP_DATE DATE, BL_STATUS NCHAR(1), FOOTAGE DECIMAL(12,4))
IF #date IS NULL
Insert into #TempList
Select mill_no, null, bl_status,footage from fn_A(0,0)
ELSE
Insert into #TempList
Select * from fn_B(0,'2006/06/06') -- also I changed date order.
Select * from #TempList

I struggled all these days to insert values into same temporary table when a given condition is met.
Given that I am on a project migrating FoxPro(which has cursors declared all over) to SQL Server this small logic needed to be implemented in multiple stored procs.
Finally, what I learned out of this is - Think Straight Before Trying Anything Different (suggestion to my co-beginners in DB migration).
DECLARE #date DATE
SET #date = '06/06/2006' --#date = null
If object_id('tempdb..#TempList') is not null drop table #TempList
Create table #TempList (MILL_NO VARCHAR(7), SHIP_DATE DATE, BL_STATUS NCHAR(1),
FOOTAGE DECIMAL(12,4))
If #date = null
-- Here I am inserting null in place of Ship_Date because fn_A returns only 3 columns in my case
Insert into #TempList
Select mill_no, null, bl_status,footage from fn_A(0,0)
--Select * from #TempList
else
Insert into #TempList
Select * from fn_B(0,#date)
Select * from #TempList
Thanks everyone for giving your inputs. Hope this helps somebody.

Related

Adding conditions to Triggers in SQL Server

I have these tables in my SQL Server database:
CREATE TABLE weather
(
weatherId integer Identity(1,1) primary key,
weatherDate datetime,
rainout BIT,
temperature float,
inchesOfRain float
)
CREATE TABLE weather_audit
(
weatherAuditId integer Identity(1,1) primary key,
weatherId integer,
date datetime,
rainout BIT,
temperature float,
inchesOfRain float
)
CREATE TABLE maintenance
(
maintenanceId integer Identity(1,1) primary key,
maintenanceDescription nvarchar(100),
dateRequested datetime,
dateResolved datetime,
currentStatus nvarchar(20),
estimatedCost decimal,
)
CREATE TABLE maintenence_audit
(
mainteneceAuditId integer Identity(1,1) primary key,
maintenanceId integer,
description nvarchar(100),
dateRequested datetime,
dateResolved datetime,
currentStatus nvarchar(20),
estimatedCost decimal,
updatedOn datetime
)
I want to set up a trigger which fires when a row is inserted into the weather table whose inchesOfRain is > 4. This is what I have now, but it isn't working:
CREATE TRIGGER tr_weather_ForInsertUpdate
ON weather
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
IF (SELECT TOP 1 inchesOfRain FROM weather) > 4
INSERT INTO weather_audit (weatherId, weatherDate, rainout, temperature, inchesOfRain)
SELECT
i.weatherId, i.weatherDate, i.rainout, i.temperature, i.inchesOfRain
FROM
Inserted AS I
END
So if I were to insert this
INSERT INTO dbo.weather (weatherDate, rainout, temperature, inchesOfRain)
VALUES ('4/21/2018', '0', '70', '6');
it would add a row to the weather table and also to the weather_audit table since the inches of rain is 6
You need to depend on your Inserted pseudo table to make the decision whether or not to add a row to the audit table - try this:
CREATE TRIGGER tr_weather_ForInsertUpdate
ON weather
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO weather_audit (weatherId, weatherDate, rainout, temperature, inchesOfRain)
SELECT
i.weatherId, i.weatherDate, i.rainout, i.temperature, i.inchesOfRain
FROM
Inserted AS I
WHERE
i.inchesOfRain > 4 -- just insert those rows with inchesOfRain > 4
END
Your trigger is all good, it just needs to be
CREATE TRIGGER tr_weather_ForInsertUpdate
ON weather
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
--Modified Code Start
DECLARE #inchesOfRain float
SELECT #inchesOfRain = inchesOfRain FROM inserted
IF #inchesOfRain > 4
BEGIN
---------------Modified COde End
INSERT INTO weather_audit (weatherId, weatherDate, rainout, temperature, inchesOfRain)
SELECT
i.weatherId, i.weatherDate, i.rainout, i.temperature, i.inchesOfRain
FROM
Inserted AS I
END
END
Update: Marc S code snippet is the perfect answer.

Insert another parameter along with table type

The table tblEffort has 3 columns EmployeeName, Effort, Date. I get the first 2 column values from a table type parameter and have to insert a common date for all these values.
do not have the option to include timesheetdate in dtCSV
There should be some other way than running an update again on the inserted columns right?
The below code gives the error - Must declare the table variable "#TimesheetDate"
CREATE TYPE dbo.SaveEffort_TableType AS TABLE
(
EmployeeName varchar(200),
Effort decimal(18,2)
);
GO
CREATE PROCEDURE SaveEmployeeEffort
(
#TimesheetDate datetime,
#dtCSV AS dbo.SaveEffort_TableType readonly
)
AS
BEGIN
INSERT INTO tblEffort(EmployeeName,Effort,[Date])
SELECT * FROM #dtCSV,#TimesheetDate
END
You need to put the variable into the SELECT clause, not the FROM clause
CREATE PROCEDURE SaveEmployeeEffort
(
#TimesheetDate datetime,
#dtCSV AS dbo.SaveEffort_TableType readonly
)
AS
BEGIN
INSERT INTO tblEffort(EmployeeName,Effort,[Date])
SELECT EmployeeName,Effort, #TimesheetDate FROM #dtCSV
END

Adding computed column in SQL

How to add computed column that calculates the sum of selected column.
this is what i've done but has an error..
ALTER TABLE dbo.tblEM_Reimbursement
ADD [Amount] AS (SELECT SUM(Total) FROM dbo.tblEM_ReimbursementEntry WHERE ReimbursementID = ReimbursementID)
it says
Msg 1046, Level 15, State 1, Line 2
Subqueries are not allowed in this context. Only scalar expressions are allowed.
Thanks in advance
You could use a user-defined function. Non tested code below.
CREATE FUNCTION dbo.Get_ReimbursementEntry (#ReimbursementID int)
RETURNS DECIMAL(10,2)
AS BEGIN
RETURN (SELECT SUM(Total) FROM dbo.tblEM_ReimbursementEntry WHERE ReimbursementID = ReimbursementID)
END
GO
ALTER TABLE dbo.tblEM_Reimbursement
ADD [Amount] AS (dbo.Get_ReimbursementEntry (ReimbursementID))
GO
but beware of the performance implications
You can use a Trigger. Trigger is a automated function written in PL/SQL whcih is called
after or before a particular event.
Read this tutorial for better understanding.
For SQL-Server read this and this.
Example:
CREATE TABLE Employee_Test
(
Emp_ID INT Identity,
Emp_name Varchar(100),
Emp_Sal Decimal (10,2)
)
INSERT INTO Employee_Test VALUES ('Anees',1000);
INSERT INTO Employee_Test VALUES ('Rick',1200);
INSERT INTO Employee_Test VALUES ('John',1100);
INSERT INTO Employee_Test VALUES ('Stephen',1300);
INSERT INTO Employee_Test VALUES ('Maria',1400);
Suppose you have another table:
CREATE TABLE Employee_Test_Audit
(
Emp_ID int,
Emp_name varchar(100),
Emp_Sal decimal (10,2),
Audit_Action varchar(100),
Audit_Timestamp datetime
)
This trigger is fired after an INSERT on the table. Let’s create the trigger as:
CREATE TRIGGER trgAfterInsert ON [dbo].[Employee_Test]
FOR INSERT
AS
declare #empid int;
declare #empname varchar(100);
declare #empsal decimal(10,2);
declare #audit_action varchar(100);
select #empid=i.Emp_ID from inserted i;
select #empname=i.Emp_Name from inserted i;
select #empsal=i.Emp_Sal from inserted i;
set #audit_action='Inserted Record -- After Insert Trigger.';
insert into Employee_Test_Audit
(Emp_ID,Emp_Name,Emp_Sal,Audit_Action,Audit_Timestamp)
values(#empid,#empname,#empsal,#audit_action,getdate());
PRINT 'AFTER INSERT trigger fired.'
GO

Select only few columns from procedure and insert into table

I have a stored procedure that returns 6 columns. But I want to take only 2 columns and insert them into my table variable.
DECLARE #CategoryTable TABLE(
CategoryId Int NOT NULL,
Name nvarchar(255) NOT NULL
)
INSERT INTO #CategoryTable EXEC [GetAllTenantCategories] #TenantId
When I run this
Column name or number of supplied values does not match table
definition
How to insert only specified columns from a stored procedure?
I do not want to use SELECT INTO as it is not supported by SQL Azure
Tried below and got Invalid object name '#Temp'
DECLARE #CategoryTable TABLE(
CategoryId Int NOT NULL,
Name nvarchar(255) NOT NULL
)
INSERT INTO #Temp EXEC [GetAllTenantCategories] 1
INSERT INTO #CategoryTable (CategoryId, Name)
SELECT CategoryId, Name from #Temp
DROP TABLE #Temp
You can create a temp table first and the INSERT the required columns in your table variable.
CREATE TABLE #temp
(
your columns and datatype
)
INSERT INTO #temp
EXEC [GetAllTenantCategories] #TenantId
Then you can,
DECLARE #CategoryTable TABLE(
CategoryId Int NOT NULL,
Name nvarchar(255) NOT NULL
)
INSERT INTO #CategoryTable (CategoryId, Name)
select CategoryId, Name from #temp
Also drop the #temp table,
DROP TABLE #temp
Refer the points taken from https://www.simple-talk.com/sql/performance/execution-plan-basics/
When the Estimated Plan is Invalid
In some instances, the estimated plan won't work at all. For example, try generating an estimated plan for this simple bit of code:
CREATE TABLE TempTable
(
Id INT IDENTITY (1 , 1 )
,Dsc NVARCHAR (50 )
);
INSERT INTO TempTable ( Dsc )
SELECT [Name]
FROM [Sales] .[Store] ;
SELECT *
FROM TempTable ;
DROP TABLE TempTable ;
You will get this error:
Invalid object name 'TempTable'.
The optimizer, which is what is used to generate Estimated Execution plans, doesn't execute T-SQL.
It does run the state­ments through the algebrizer , the process outlined earlier that is responsible for verifying the names of database objects. Since the query has not yet been executed, the temporary table does not yet exist. This is the cause of the error.
Running this same bit of code through the Actual execution plan will work perfectly fine.
Hope you got why your temp table approach not worked :) Because you might tried as T-SQL
We can use OPENQUERY
SELECT EmployeeID,CurrentSalary INTO #tempEmp
FROM OPENQUERY(LOCALSERVER,'Exec TestDB.dbo.spEmployee')

Get SQL Insert to work when PK is supplied or NOT

I have the following stored procedure:
ALTER Procedure dbo.APPL_ServerEnvironmentInsert
(
#ServerEnvironmentName varchar(50),
#ServerEnvironmentDescription varchar(1000),
#UserCreatedId uniqueidentifier,
#ServerEnvironmentId uniqueidentifier OUTPUT
)
WITH RECOMPILE
AS
-- Stores the ServerEnvironmentId.
DECLARE #APPL_ServerEnvironment TABLE (ServerEnvironmentId uniqueidentifier)
-- Insert the data into the table.
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId
)
OUTPUT Inserted.ServerEnvironmentId INTO #APPL_ServerEnvironment
VALUES
(
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId
)
-- If #ServerEnvironmentId was not supplied.
IF (#ServerEnvironmentId IS NULL)
BEGIN
-- Get the ServerEnvironmentId.
SELECT #ServerEnvironmentId = ServerEnvironmentId
FROM #APPL_ServerEnvironment
END
The ServerEnvironmentId column is a primary key with a default set on it, which is (newsequentialid()).
I need this stored procedure to work for 2 scenarios:
Value supplied for ServerEnvironmentId - WORKS.
Value not supplied for ServerEnvironmentId - DOES NOT WORK - CANNOT INSERT NULL VALUE. I thought by setting a default on this column this would be fine.
Someone please help to ammend this procedure so that it may work for both scenarios. Solution needs to have minimal changes as all sp's currently following this trend.
Default values are only applied on inserts if the column is not included in the INSERT list. I'd recommend the following not entirely trivial change (I've commented out the lines to be removed):
ALTER Procedure dbo.APPL_ServerEnvironmentInsert
(
#ServerEnvironmentName varchar(50),
#ServerEnvironmentDescription varchar(1000),
#UserCreatedId uniqueidentifier,
#ServerEnvironmentId uniqueidentifier OUTPUT
)
WITH RECOMPILE
AS
---- Stores the ServerEnvironmentId.
--DECLARE #APPL_ServerEnvironment TABLE (ServerEnvironmentId uniqueidentifier)
IF #ServerEnvironmentName is null
SET #ServerEnvironmentName = newid()
-- Insert the data into the table.
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId
)
--OUTPUT Inserted.ServerEnvironmentId INTO #APPL_ServerEnvironment
VALUES
(
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId
)
---- If #ServerEnvironmentId was not supplied.
--IF (#ServerEnvironmentId IS NULL)
--BEGIN
-- -- Get the ServerEnvironmentId.
-- SELECT #ServerEnvironmentId = ServerEnvironmentId
-- FROM #APPL_ServerEnvironment
--END
The default constraint will not be used by this procedure, but you can leave it in place if there are other places where rows may be added to the table.
(My first answer was long and so it this one, so I'm posting a second answer.)
I missed that you were using NewSequentialId. Again, if a column is specified within the insert statement, any DEFAULT values assigned to that column will not be used [unless you use the DEFAULT keyword in the INSERT statement, but that's still all or nothing--you can't say "if #Var is null then DEFAULT"]. I think you are stuck with simple branching and semi-redundant code, along the lines of:
ALTER Procedure dbo.APPL_ServerEnvironmentInsert
(
#ServerEnvironmentName varchar(50),
#ServerEnvironmentDescription varchar(1000),
#UserCreatedId uniqueidentifier,
#ServerEnvironmentId uniqueidentifier OUTPUT
)
WITH RECOMPILE
AS
-- Stores the ServerEnvironmentId.
DECLARE #APPL_ServerEnvironment TABLE (ServerEnvironmentId uniqueidentifier)
IF #ServerEnvironmentId is null
BEGIN
-- ServerEnvironmentId not provided by user, generate during the insert
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId
)
OUTPUT Inserted.ServerEnvironmentId INTO #APPL_ServerEnvironment
VALUES
(
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId
)
-- Get the new ServerEnvironmentId
SELECT #ServerEnvironmentId = ServerEnvironmentId
FROM #APPL_ServerEnvironment
END
ELSE
BEGIN
-- ServerEnvironmentId is provided by user
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId,
ServerEnvironmentId
)
OUTPUT Inserted.ServerEnvironmentId INTO #APPL_ServerEnvironment
VALUES
(
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId,
#ServerEnvironmentId
)
END
(Why lock the entire table during the insert?)
Help to Simplify SQL Insert which uses NEWSEQUNETIALID() column default