Stored Procedure not executing in SQL SERVER? - sql-server

I'm trying to write a somewhat simple stored procedure. I first want to verify if there is anything in the table; if there is to TRUNCATE it, if there isn't to populate it with some data. What happens is, it gets execute without any error, but nothing happens to the table. It is as it was before executing it.........empty.
ALTER PROCEDURE [dbo].[LoadReportDataCI]
AS
If (Select Count(*) from tbl_TempTableReport)>0
BEGIN
Truncate table tbl_TempTableReport
END
Begin
INSERT INTO tbl_TempTableReport (userID, VendorID, VendorName, UnitCost, UnitCount, CostValue)
SELECT
'1234',
VendorID,
VendorName,
InvValue,
BegInvOnHand,
BegCurrentValue
From vVendorsAndInvONHand
END
If I highlight starting at INSERT until the END, the data gets populated in the table, but otherwise it doesn't work. Shed some light anyone?

There is no point to checking if there are rows before truncating. It is far faster to just truncate than checking for the existence of rows. If there are no rows it will still run just fine.
ALTER PROCEDURE [dbo].[LoadReportDataCI]
AS
Truncate table tbl_TempTableReport;
INSERT INTO tbl_TempTableReport
(
userID
, VendorID
, VendorName
, UnitCost
, UnitCount
, CostValue
)
SELECT
'1234'
, VendorID
, VendorName
, InvValue
, BegInvOnHand
, BegCurrentValue
From vVendorsAndInvONHand;

Use below code to execute your stored procedure, I have moved your second begin after AS
ALTER PROCEDURE [dbo].[sp_LoadReportDataCI]
AS
Begin
If (Select Count(*) from tbl_TempTableReport)>0
BEGIN
Truncate table tbl_TempTableReport
END
INSERT INTO tbl_TempTableReport (userID, VendorID, VendorName, UnitCost, UnitCount, CostValue)
SELECT
'1234',
VendorID,
VendorName,
InvValue,
BegInvOnHand,
BegCurrentValue
From vVendorsAndInvONHand
END

I guess, you didn't execute the Stored Procedure. Did you EXEC the LoadReportDataCI after running the ALTER script?

Related

How do I force a drop temp table command to fully drop the table?

I'm working on a script, just experimenting and developing. A lot of what I do involves temp tables, where I will select ... into #SomeTable from ..., at least in the initial experimentation/early dev stage.
Then I'll look at the results, make some changes, and go again. But to make things a little easier on myself, I also have a drop table if exists #SomeTable, so I can just rerun the code. So far so good. But, if I add a column to the temp table and then try to access it, I get the error Invalid column name 'newColumn'. I can avoid the error by executing JUST the drop statement, and then executing the whole script, but I would rather not have to do that. As I understand it, there is some caching of temp tables that goes on, and I wonder if that's the culprit. In any case, is there any way to fix this?
Edit: Here is a short script demonstrating the problem. Run the script, then uncomment both comments and run it again:
drop table if exists #DemoTable
select column1 = '1'
,column2 = '2'
-- ,column3 = '3'
into #DemoTable
select column1
,column2
-- ,column3
from #DemoTable
In SSMS you can just add a GO statement to separate the code in 2 batches.
This way the drop is executed before the 2nd part of the script is checked for errors.
drop table if exists #DemoTable
GO
select column1 = '1'
,column2 = '2'
-- ,column3 = '3'
into #DemoTable
select column1
,column2
-- ,column3
from #DemoTable
I have tried to follow the steps mentioned in the question.
Please find the following query samples using Northwind Database.
Added a new column to the temp table and also updated it sucessfully.
-- Create the temporary table #temp_Employees from a physical table called 'Employee' in schema 'dbo' in database 'Northwind'
SELECT EmployeeID, FirstName, LastName , BirthDate
INTO #temp_Employees
FROM [Northwind].[dbo].[Employees]
-- SELECT data from temptable '[#temp_Employees]'
SELECT * FROM #temp_Employees;
-- Add a new column '[City]' to table '[#temp_Employees]'
ALTER TABLE #temp_Employees
ADD [City] NVARCHAR(15) NULL
GO
-- SELECT data from temptable '[#temp_Employees]'
SELECT * FROM #temp_Employees;
-- UPDATE the new column '[City]' in the table '[#temp_Employees]'
UPDATE T
SET T.[City]=E.[City]
FROM #temp_Employees T INNER JOIN [Northwind].[dbo].[Employees] E ON T.EmployeeID=E.EmployeeID;
-- SELECT data from temptable '[#temp_Employees]'
SELECT * FROM #temp_Employees;
-- Drop the temptable if it already exists
IF OBJECT_ID('tempDB..#temp_Employees', 'U') IS NOT NULL
DROP TABLE #temp_Employees;
GO
-- SELECT data from temptable '[#temp_Employees]'
SELECT * FROM #temp_Employees;
Thank you.

SQL Server stored procedure to run insert/update in transaction

I have to execute blocks of T-SQL with insert and update instructions.
Let's say I have these two blocks of code, and I have no direct control on them.
Block #1:
insert into mytable (id, col1)
values ((select max(id) + 1 from mytable), 'foo');
insert into non_existing_table (id, col1)
values ((select max(id) from mytable), 'bar');
Block #2:
insert into mytable (id, col1)
values ((select max(id) + 1 from mytable), 'foo');
insert into anothertable (id, col1)
values ((select max(id) from mytable), 'bar');
In the first block there are two instructions, the first is ok, the second one fails because the second table does not exists.
In the second block there are also two instructions, both are ok.
What I want to do is run both two blocks
The first block should do nothing in the end, since the second instruction fails, the first should be rolled back
The second block is fine, since there is no error, both inserts should be committed
What's the correct way to do this? Maybe a stored procedure that accepts a full text parameter and run all the code as a transaction? How can I do that in SQL Server?
You can create a stored procedure with transactions.
Try like this.
CREATE PROCEDURE [dbo].[Procedure_name]
#iErrorCode int OUTPUT,
--other parameters
AS
BEGIN
BEGIN TRY
begin tran
insert into mytable (id,col1) values ((select max(id)+1 from mytable),'foo');
insert into non_existing_table (id,col1) values ((select max(id) from mytable),'bar');
--other queries
commit tran
SELECT #iErrorCode =##ERROR;
END TRY
BEGIN CATCH
rollback tran
Select ERROR_NUMBER();
Select ERROR_MESSAGE();
SELECT #iErrorCode =##ERROR
END CATCH
END

I would like to know on how to convert Oracle triggers into SQL Server triggers

As I understand, SQL SERVER Triggers does not support FOR EACH ROW. Also I am aware that you have to use inserted tables and deleted tables. Other than that, I have no clue how to write SQL Server triggers. They look so different. Can some help please?
Below is the code for Oracle Triggers
create or replace TRIGGER Ten_Percent_Discount
BEFORE INSERT OR UPDATE ON Bookings
FOR EACH ROW
DECLARE CURSOR C_Passengers IS
SELECT StatusName
FROM Passengers
WHERE PassengerNumber = :NEW.Passengers_PassengerNumber;
l_status_name Passengers.StatusName%TYPE;
BEGIN
OPEN C_Passengers;
FETCH C_Passengers INTO l_status_name;
CLOSE C_Passengers;
Below is what I have written so far. I know I am using the inserted tables wrong
IF l_status_name = 'Regular'
THEN
:New.TotalCost := 0.90 * :New.TotalCost;
END IF;
END;
create TRIGGER Ten_Percent_Discount
ON Customer
FOR INSERT ,UPDATE
AS
DECLARE C_Passengers CURSOR FOR
SELECT StatusLevel
FROM Customer
WHERE CustomerID = inserted.CustomerID
Thanks for all the help in advance.
Table structure for customer
Table structure for Order
Below answer is only for reference purpose that you can use to build gradually towards final solution:
create table dbo.customer
(
customerid varchar(10),
firstname nvarchar(50),
statuslevel varchar(50)
)
go
create table dbo.customerorder
(
orderid varchar(10),
totalprice numeric(5,2),
productid varchar(10),
customerid varchar(10)
)
go
go
create trigger dbo.tr_customer on dbo.customer for insert,update
as
begin
update co
set co.totalprice = .9*co.totalprice
from dbo.customerorder co
inner join inserted i
on co.customerid = i.customerid
where i.statuslevel = 'Standard'
end
go
--test for above code
insert into dbo.customer values (1,'jayesh','')
insert into dbo.customerorder values (1,500.25,1,1)
insert into dbo.customerorder values (1,600.25,2,1)
select * from dbo.customer
select * from dbo.customerorder
update dbo.customer set statuslevel = 'Standard' where customerid = 1
select * from dbo.customer
select * from dbo.customerorder
But what I am pretty sure is that when customer is created for the first time, there will not be any orders to apply discounts on, so you will certainly need UPDATE Trigger as well.

How to avoid bulk data duplicate values when insert in to a table in SQL Server 2012

The problem im trying to solve is about avoiding duplicate data getting into my table. I'm using xml to send bulk data to a stored procedure. The procedure I wrote works with 100, 200 records. But when it comes to 20000 of them there is a time out exception.
This is the stored procedure:
DECLARE #TEMP TABLE (Page_No varchar(MAX))
DECLARE #TEMP2 TABLE (Page_No varchar(MAX))
INSERT INTO #TEMP(Page_No)
SELECT
CAST(CC.query('data(PageId)') AS NVARCHAR(MAX)) AS Page_No
FROM
#XML.nodes('DocumentElement/CusipsFile') AS tt(CC)
INSERT INTO #TEMP2(Page_No)
SELECT Page_No
FROM tbl_Cusips_Pages
INSERT INTO tbl_Cusips_Pages(Page_No, Download_Status)
SELECT Page_No, 'False'
FROM #TEMP
WHERE Page_No NOT IN (SELECT Page_No FROM #TEMP
INTERSECT
SELECT Page_No FROM #TEMP2)
How can I solve this? Is there a better way to write this procedure?
As was already suggested, NVARCHAR(MAX) column/variable is very slow and has limited options. If you can change it, it would help a lot.
MERGE tbl_Cusips_Pages
USING (
SELECT
CAST(CC.query('data(PageId)') AS NVARCHAR(4000))
FROM
#XML.nodes('DocumentElement/CusipsFile') AS tt(CC)
) AS source (Page_No)
ON tbl_Cusips_Pages.Page_No = source.Page_No
WHEN NOT MATCHED BY TARGET
THEN INSERT (Page_No, Download_Status)
VALUES (source.Page_No, 'false')
Anyway, your query is not that bad either, just put the queries directly into the third one (TEMP2 one for sure) instead of inserting the data into the table variables. Table variables are quite slow in comparison.
Replace last INSERT Statement with following Script, I have replace IN Clause With NOT EXISTS that may help you for better performance.
DECLARE #CommanPageNo TABLE (Page_No varchar(MAX))
INSERT INTO #CommanPageNo SELECT Page_No FROM #TEMP
INTERSECT
SELECT Page_No FROM #TEMP2
INSERT INTO tbl_Cusips_Pages(Page_No, Download_Status)
SELECT Page_No, 'False'
FROM #TEMP
WHERE NOT EXISTS (SELECT 1 FROM #CommanPageNo WHERE Page_No=#CommanPageNo.Page_No)

a select statement in a transaction against a loopback linked server never stops

In Sql Server 2008 r2, I have a table called Emp, and I'm trying to update some values in a transaction (outer tran), now after the update and before the commit, I began another transaction, in witch i tried to select data from the same table (Emp) but via a loopback linked server.
the tsql look like this:
USE MASTER
GO
EXEC sp_addlinkedserver #server = N'loopback',#srvproduct=N'',#provider = N'SQLNCLI', #datasrc = ##SERVERNAME,#catalog = 'MstrDtl'
GO
EXEC sp_serveroption loopback,N'remote proc transaction promotion','FALSE'
Go
create SYNONYM loopy FOR loopback.MstrDtl.dbo.Emp
use MstrDtl
BEGIN TRAN OuterTran
BEGIN
update table dbo.Emp set Salary = 123456 where Name='abcdx'
BEGIN TRAN InnerTran
select Salary from loopy where Name = 'abcdx'
COMMIT TRAN InnerTran
ROLLBACK TRAN OuterTran
END
so i have two questions:
can i get old values (the affected rows with the update) in the query to loopback inside the InnerTran using this way?
the query never stops, any idea?
To answer your questions:
No, you cannot get the old values in that way; you'll get blocked (see #2) or you'll get the new values.
The reason the query never stops is because you're blocking yourself (technically, you're deadlocking yourself.) Your outer transaction is holding a lock on that row (page actually) and therefore the loopback query is blocked until the update lock is released. You could (but shouldn't) specify WITH (NOLOCK) on your loopback query but that will actually return the updated but uncommitted row.
If you want the OLD values in your query use the OUTPUT clause. http://msdn.microsoft.com/en-us/library/ms177564.aspx
CREATE TABLE #emp
(
id INT IDENTITY PRIMARY KEY CLUSTERED,
empName VARCHAR(255),
salary MONEY
)
go
INSERT INTO #emp(empName, salary)
SELECT 'bill', 5000
UNION ALL
SELECT 'ted', 5000
UNION ALL
SELECT 'cheech', 35000
UNION ALL
SELECT 'chong', 15000
UNION ALL
SELECT 'tango', 70000
UNION ALL
SELECT 'Cash', 200000
GO
DECLARE #oldValues TABLE
(
id INT,
empname VARCHAR(255),
salary money
)
UPDATE #emp SET salary = salary + 500
OUTPUT DELETED.* INTO #oldValues
WHERE empName = 'bill'
SELECT E.empName, E.salary AS NewSalary, O.salary AS OldSalary
FROM #emp E
INNER JOIN #oldValues O
ON E.id = O.id
DROP TABLE #emp

Resources