I am trying to create a procedure that displays all of the tables created by a specified user. Here is what I have so far:
CREATE OR REPLACE PROCEDURE user_tables
#username VARCHAR(50),
#result varchar(100000) OUTPUT
AS
BEGIN
-- Execution section
Set result = SELECT * FROM ALL_TABLES WHERE OWNER = #username;
EXCEPTION
-- Exception section
WHEN no_data_found THEN
dbms_output.put_line('User does not exist');
WHEN others THEN
dbms_output.put_line('Error!');
END;
I was wondering if this is the right path, and how I should go about completing this task
Here is a hint
BEGIN
FOR tn IN (SELECT table_name FROM all_tables /*WHERE owner = vc_User_Name*/)
LOOP
-- Display some stuff
DBMS_OUTPUT.PUT_LINE(tn.table_name);
END LOOP;
END;
/
Related
I had written and successfully created a stored procedure by the query
CREATE PROCEDURE [dbo].[Table_Load]
AS
BEGIN
SET NOCOUNT ON
DECLARE #Row_Count_Inserted BIGINT
DROP TABLE IF EXISTS DBB.dbo.Table;
SELECT *
INTO DBB.dbo.Table
FROM
(SELECT *
FROM DBB.dbo.customer_table) y
SET #Row_Count_Inserted = ##RowCount
SELECT #Row_Count_Inserted Row_Count_Inserted
END
This shows that the stored procedure is created and is present in the database. But when I query the table 'Table' using
SELECT * FROM DBB.dbo.Table
I get an error
Invalid object name
How can I solve this issue? I have refreshed the database as well but it does not work.
Here is your procedure greatly simplified to remove a lot of extra code. Assuming you have the table customer_table this will work just fine.
CREATE or alter PROCEDURE [dbo].[Table_Load] As
Begin
SET NOCOUNT ON
drop table If Exists dbo.MyTable;
Select *
into MyTable
from customer_table
select Row_Count_Inserted = ##RowCount
End
GO
exec Table_Load
GO
select * from MyTable
We use a suite of stored procedures to fulfill one of our ETL pipelines, which relies on linked servers using a push strategy. The stored procedures are run one-per-step in a SQL Server Agent job. The servers exist in the same VLAN and have a 10GBPS connection.
We realize a pull strategy is ideal, and are working to apply this approach across our workloads.
The ETL agent is typically successful and has been a working solution for quite some time. Intermittently one or more of the stored procedures will report a successful execution but in truth it does not execute. I have verified this scenario on numerous occassions.
The agent history indicates no errors have occurred and our custom error table (populated by our error handler stored procedure) shows no errors for the migration. All stored procedures have been verified to be working correctly and are free of logic bugs, as evidenced by the fact that in most cases data is INSERT|UPDATE|DELETE(ed) successfully.
Manually executing the failed stored procedure does not produce different results. The confusing part about the situation is that if a query contained within the stored procedure is extracted and executed manually, it succeeds in INSERT|UPDATE|DELETE(ing) the data.
My best guess is that this is perhaps being caused by a cached query plan. Though, I'm entirely unsure.
Our stored procedures for this use case always contain a try/catch to handle and log any errors. In structure, they usually resemble something like the following:
CREATE PROCEDURE dbo.some_etl_proc
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRY
---------
-- delete
---------
DELETE at
FROM LINKED_SERVER.ANOTHER_DB.dbo.another_table AS at
LEFT JOIN SOME_DB.dbo.some_table AS st
ON st.some_table_id = at.some_table_id
WHERE st.some_table_id IS NULL;
---------
-- update
---------
UPDATE at
SET col_1 = st.col_1
, col_2 = st.col_2
FROM LINKED_SERVER.ANOTHER_DB.dbo.another_table AS at
JOIN SOME_DB.dbo.some_table AS st
ON st.some_table_id = at.some_table_id;
---------
-- insert
---------
INSERT INTO LINKED_SERVER.ANOTHER_DB.dbo.another_table (col_1, col_2)
SELECT st.col_1
, st.col_2
FROM SOME_DB.dbo.some_table AS st
LEFT JOIN LINKED_SERVER.ANOTHER_DB.dbo.another_table AS at
ON at.some_table_id = st.some_table_id
WHERE at.some_table_id IS NULL;
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN;
-- we log the error here using a custom sproc
EXEC dbo.error_handler
RETURN 55555;
END CATCH;
END;
Our error handler looks like:
CREATE PROCEDURE dbo.error_handler
AS
DECLARE #errmsg NVARCHAR(2048)
, #severity TINYINT
, #state TINYINT
, #errno INT
, #proc sysname
, #lineno INT;
SELECT #errmsg = ERROR_MESSAGE()
, #severity = ERROR_SEVERITY()
, #state = ERROR_STATE()
, #errno = ERROR_NUMBER()
, #proc = ERROR_PROCEDURE()
, #lineno = ERROR_LINE();
IF #errmsg NOT LIKE '***%'
BEGIN
SELECT #errmsg = N'*** ' + COALESCE(QUOTENAME(#proc), '<dynamic SQL>') + N', Line ' + LTRIM(STR(#lineno)) + N'. Errno ' + LTRIM(STR(#errno)) + N': ' + #errmsg;
END;
INSERT INTO dbo.db_error
SELECT GETDATE()
, SYSTEM_USER
, #errno
, #severity
, #state
, #lineno
, #errmsg
, #proc;
RAISERROR('%s', #severity, #state, #errmsg);
I am running the following query:
SELECT * INTO dbo.2015_10_2_cs FROM dbo.2015_10_2
IF NOT EXISTS
(SELECT type FROM sys.indexes WHERE object_id = object_id('dbo.2015_10_2_cs')
AND NAME ='cci' AND type = 5)
BEGIN
CREATE CLUSTERED COLUMNSTORE INDEX cci
ON dbo.2015_10_2_cs
DROP TABLE dbo.2015_10_2
EXEC sp_rename "dbo.2015_10_2_cs" , "dbo.2015_10_2"
END
and I want to make sure that the part where I am renaming the table dbo.2015_10_2_cs to dbo.2015_10_2 is done successfully (without losing any data).
The step inside the loop should be surrounded with SQL transaction to keep the process safe and reliable (in case if any step will fail).
Could anyone help with this? Thanks in advance.
EXEC sp_rename "dbo.2015_10_2_cs" , "dbo.2015_10_2"
This will not do what you expect. The new table will be named [dbo].[dbo.2015_10_2] if you specify the schema name in the new table name. Renamed tables are implicitly in the existing table's schema since one must use ALTER SCHEMA instead of sp_rename to move an object between schemas.
There are a number of other problems with your script. Because the table name starts with a number, it doesn't conform to regular identifier naming rules and must be enclosed in square brackets or double quotes. The literal parameters passed to sp_rename should be single quotes. You can also check to stored procedure return code to ascertain success or failure. The example below performs these tasks in a transaction with structured error handling.
DECLARE #rc int;
BEGIN TRY
BEGIN TRAN;
IF NOT EXISTS
(SELECT type FROM sys.indexes WHERE object_id = object_id(N'dbo.2015_10_2_cs')
AND NAME ='cci' AND type = 5)
BEGIN
CREATE CLUSTERED COLUMNSTORE INDEX cci
ON dbo.[2015_10_2_cs];
DROP TABLE dbo.[2015_10_2];
EXEC #rc = sp_rename 'dbo.[2015_10_2_cs]' , '2015_10_2';
IF #rc <> 0
BEGIN
RAISERROR('sp_rename returned return code %d',16,1);
END;
END;
COMMIT;
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH;
You can use an EXISTS checking for the tablename and schema.
IF NOT EXISTS (SELECT 'table does not exist' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'2015_10_2'AND TABLE_SCHEMA = 'dbo')
BEGIN
RAISERROR('The table doesn''t exist!!!!', 16, 1)
END
sp_rename won't make you lose table contents, it will just change the table reference name and update all it's contraints and indexes references. It will also raise an error if the table to rename does not exist. Maybe what you want is to wrap your process in a transaction and rollback if something fails.
EDIT:
For basic transaction handling you can use the following. Please read the documentation for using transaction, it might take a while to know how it works correctly.
IF OBJECT_ID('tempdb..#Test') IS NOT NULL
DROP TABLE #Test
CREATE TABLE #Test (Number INT)
SELECT AmountRecords = COUNT(1) FROM #Test -- AmountRecords = 0
BEGIN TRY
BEGIN TRANSACTION
-- Do your statements here
INSERT INTO #Test (Number)
VALUES (1)
DECLARE #errorVariable INT = CONVERT(INT, 'NotAnInteger!!') -- Example of error: can't convert
COMMIT
END TRY
BEGIN CATCH -- If something goes wrong
IF ##TRANCOUNT > 0 -- ... and transaction is still open
ROLLBACK -- Revert statements from the BEGIN TRANSACTION onwards
END CATCH
SELECT AmountRecords = COUNT(1) FROM #Test -- AmountRecords = 0 (the transaction was rolled back and the INSERT reverted)
Basically you use BEGIN TRANSACTION to initiate a restore point to go back to if something fails. Then use a COMMIT once you know everything is OK (from that point onwards, other users will see the changes and modifications will be persisted). If something fails (you need TRY/CATCH block to handle errors) you can issue a ROLLBACK to revert your changes.
i have created one store procedure for the user wise getting feed list in the SQL server. in this store procedure, i have used the cursor and temp table. so I am run the store procedure that time I am getting like this error "Cannot drop the table '#h', because it does not exist or you do not have permission." on my local PC.
this is my store procedure=>
alter PROCEDURE [dbo].[UserList]
AS
BEGIN
DECLARE #UserId Int
DECLARE csrUsers CURSOR FOR
SELECT UserId FROM dbo.users
OPEN csrUsers
FETCH NEXT FROM csrUsers INTO #UserId
WHILE ##FETCH_STATUS = 0
BEGIN
print #UserId
SELECT * into #h FROM feed where feed = #UserId
FETCH NEXT FROM csrUsers INTO #UserId
END
CLOSE csrUsers
DEALLOCATE csrUsers
select * from #h
drop table #h
END
any one have the idea where is my problem please let me know how can do that.
No need for a cursor is what you are doing
alter PROCEDURE [dbo].[UserList]
AS
BEGIN
SELECT *
into #h
FROM feed where c.feed in(SELECT UserId FROM dbo.users)
begin try
select * from #h
end try
begin catch
end catch
begin try
drop table #h
end try
begin catch
end catch
end
go
If you're not getting any data returned then your 'into' won't create the temp table and therefore you cannot drop it by the way.
BEGIN TRAN
SET XACT_ABORT ON
GO
BEGIN TRY
IF OBJECT_ID('dbo.Offer_GetByStudyId', 'p') IS NULL
EXEC ('CREATE PROCEDURE Offer_GetByStudyId as select 1')
END TRY
BEGIN CATCH
THROW;
END CATCH
GO
IF ##error <> 0 and ##trancount > 0 ROLLBACK
IF ##trancount = 0 BEGIN SET NOCOUNT ON; SET NOEXEC ON; END
GO
BEGIN TRY
ALTER PROCEDURE dbo.Offer_GetByStudyId
#StudyId NVARCHAR(MAX) = NULL
AS
BEGIN
DECLARE #Conditions NVARCHAR(MAX) = '';
IF #StudyId IS NOT NULL
BEGIN
SET #Conditions = #Conditions + ' AND o.StudyId = ' + cast(#StudyId as varchar(10))
END
DECLARE #sql NVARCHAR(MAX) = 'SELECT
o.StudyId as StudyId,
o.SampleId as SampleId,
o.Status as Status,
o.Title as Title,
o.Topic as Topic,
o.Description as Description,
o.TestOffer as TestOffer,
T.CPI as CPI
FROM Offers o
LEFT JOIN [dbo].[Terms] T ON (o.[Id] = T.[OfferId]) AND T.Active = 1
WHERE 1 = 1' + #Conditions
EXEC(#sql)
END
END TRY
BEGIN CATCH
THROW;
END CATCH
This is my SQL script, I'm trying to have a multi batch script run as a single transaction, so if one statement fails, all of it will be rolled back. But I here keep getting this error:
Incorrect syntax near BEGIN. expecting EXTERNAL
The begin they are talking about is the one after:
#StudyId NVARCHAR(MAX) = NULL
You need to remove your "GO" statements. These are not part of the TSQL language, they are just statements to tell SSMS/SQLCMD that the batch above should be executed. I'm not clear on the behavior of a transaction split across several GO statements. I would start my removing the "GO"s.
https://msdn.microsoft.com/en-us/library/ms188037.aspx
If you take out the statement ALTER PROCEDURE dbo.Offer_GetByStudyId (Line 22 - 47) from TRY CATCH it will work. i.e delete TRY CATCH (Line 20 and Line 48 - 51)
I've realised I've buried the answer in the below, so I'll bring it up to the top to make it clearer: you cannot wrap any flow control statements around an attempt to create or alter a procedure
A simpler example demonstrates the problem:
create procedure ABC
as
go
select * from sys.objects
alter procedure ABC as
Which produces the message:
Msg 111, Level 15, State 1, Procedure ABC, Line 2
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
This is explicitly documented for CREATE PROCEDURE but for some reason isn't for ALTER PROCEDURE.
The CREATE PROCEDURE statement cannot be combined with other Transact-SQL statements in a single batch.
So the upshot is, you cannot wrap any flow control statements around an attempt to create or alter a procedure.
The reason is actually pretty simple - BEGIN and END aren't required around the body of the stored procedure - and a stored procedure can actually contain multiple "top-level" BEGIN/END pairs:
create procedure ABC as
begin
select * from sys.objects
end
begin
select * from sys.columns
end
is fine - so the only way that SQL Server knows the extent of a stored procedure, when it's being defined, is "from the CREATE/ALTER PROCEDURE until the end of the batch."