SQL Server : create temp table in a stored procedure - sql-server

I am creating procedure for creating temporary table's but I want to make this more general instead of for just one original table's temporary
ALTER PROCEDURE [dbo].[CREATE_TEMP_TABLES]
AS
IF NOT EXISTS (SELECT * FROM SYS.TABLES
WHERE NAME=N'TEMP_FactAdditional' AND type ='U')
BEGIN
CREATE TABLE dbo.TEMP_FactAdditional
(
[ProductKey] [int] NOT NULL,
[CultureName] [nvarchar](50) NOT NULL,
[ProductDescription] [nvarchar](max) NOT NULL
)
END
GO
so IF NOT EXISTS (SELECT * FROM SYS.TABLES WHERE NAME=N'TEMP_FactAdditional' AND type ='U') in here I see its only creating TEMP_FactAdditional table and I have like 8 or 9 original tables which each of them is different, CREATE TABLE dbo.TEMP_FactAdditional I am thinking to add some function or method to make more general but I don't have that much knowledge about it, I am designing warehouse, and my first step is to make more efficient to transfer data's from DB to DB. such as here in the photo . Can someone help me to make procedure more efficient?

Well, I am not going to comment on the overall approach, but if you want a general way to create tables to move data into, you could do something like this....
SELECT *
INTO my_new_table_name
FROM my_old_table_name
WHERE 1 = 0
This will create the new table with the same structure and no data. Then you could theoretically write the procedure to use dynamic SQL to run this code for a list of tables, thus "creating" a number of tables in an abstract case. You could pass in two parameters, the two table names.

Related

Generate SQL script to create or alter table / stored procedures

I am creating a SQL script that will check weather the object is there or not and then do create or alter based on that.
if not exists (select * from sysobjects where name='MyTableName' and xtype='U')
create table MyTableName(
Id int not null,
Name varchar(150) not null
)
Else
--Alter
Now having to do this for a bigger database which has more than 150 table.
Is there any way I can generate this automatically for tables and stored procedures?
As far as I can judge: Your question already includes the anser - NO it can not be done! The Thing is this: you COULD spool the metadata of tables etc. IF the objects existed in an Environment... as you arleady mentioned this is not the case - so how should a function / script / procedure be able to KNOW which columns etc. have to be created for which Table? Or what has to be altered if the table already existed?

What is the best practice to insert multiple records to DB and get multiple records from DB in single instance using BizTalk?

I want to develop a BizTalk orchestration. Which should insert multiple records into multiple DB tables and retrieve inserted records from multiple DB tables, in single instance of orchestration. For this requirement, I'm able to insert the data in one instance, but seeing difficulty to retrieve the inserted data for that instance, as all the records has unique values for each record. For my situation, I should use stored procedures, to apply some other business logic. So I have 2 different methods by using "Wcf_Custom Adapter composite feature" by calling stored procedures, as stated below.
-> Method1
I have to develop a Stored procedure, which takes LoadDate("2016-05-12 10:11:22.147") as parameter along with inserting values and it will take care of inserting the records for that instance, by keeping the given LoadDate. Then immediately it will call Get stored procedure, which takes the LoadDate("2016-05-12 10:11:22.147") as parameter, then it will retrieve the recently inserted records from DB based on LoadDate value.
I know, Retrieving the data based on a date value from sql server is a bad practice and it will give performance issues too.
-> Method2
I'll design the inserting tables, with bool data type column name "New" and value will be 0 or 1. I'll develop a Insert Stored procedure, which inserts the data by giving the "New" column value as "1". Then immediately it will call Get stored procedure, which will not take no parameters, then it will retrieve the recently inserted records which are having "New" column indicator "1" from DB tables. Once it retrieves the data, then it will update "New" column value to "0".
I prefer this method2. But, do we have better option?
As #johns-305 mentioned in his comment. You shall use table value param in your sp. and assembly all your data in orchestration then make a call to this sp.
A sample sp may like below:
CREATE TYPE [dbo].[SampleDataTable_Type] AS TABLE(
[ID] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO
CREATE PROCEDURE [dbo].[sp_InsertSampleTableData]
(
#LoadDate DATETIME,
#data [SampleDataTable_Type] READONLY
)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO your_table(id, name,)
SELECT id, name FROM #data;
--Do whatever you want
SET NOCOUNT OFF
END
GO
I think your stored procedure may look like this:
create procedure myProc
#a int, #b varchar(100)
as
insert myTable(a,b,c)
OUTPUT inserted.* --this line
select a,b,c
from somewhere
where a=#a and b=#b

Disable auto creating statistics on table

Is there any possibility to disable auto creating statistics on specific table in database, without disabling auto creating statistics for entire database?
I have a procedure wich written as follow
create proc
as
create table #someTempTable(many columns, more than 100)
inserting into #someTempTable **always one or two row**
exec proc1
exec proc2
etc.
proc1, proc2 .. coontains many selects and updates like this:
select ..
from #someTempTable t
join someOrdinaryTable t2 on ...
update #someTempTable set col1 = somevalue
Profiler shows that before each select server starts collecting stats in #someTempTable, and it takes more than quarter of entire execution of proc. Proc is using in OLPT processing and should works very fast. I want to change this temporary table to table variable(because for table variables server doesn't collect stats) but can't because it lead me to rewrite all this procedures to passing variables between them and all of this legacy code should be retests. I'm searching alternative way how to force server to behave temporary table like table variables in part of collecting stats.
P.S. I'm know that stats is useful thing but in this case it's useless because table alway contains small amount of records.
I assume you know what you are doing. Disabling a statistics is generally a bad idea. Anyhow:
EXEC sp_autostats 'table_name', 'OFF'
More documentation here: https://msdn.microsoft.com/en-us/library/ms188775.aspx.
Edit: OP clarified that he wants to disable statistics for a temp table. Try this:
CREATE TABLE #someTempTable
(
ID int PRIMARY KEY WITH (STATISTICS_NORECOMPUTE = ON),
...other columns...
)
If you don't have a primary key already, use an identity column for a PK.

Is there a way I can create a unique Id for a table inserted with a stored proc without using Identity

I have a table defined like this:
CREATE TABLE [dbo].[Test] (
[TestId] INT IDENTITY (1, 1) NOT NULL,
[Title] VARCHAR (100) NOT NULL,
....
When my application makes a copy of a test so it is available to a user it uses a stored procedure to do this. Here's a shortened version of what I have inside that stored procedure.
INSERT INTO dbo.Test
(Title, ....)
SELECT Title, ....
FROM Test
WHERE TestId = #TestId;
So then for example a table with a TestId of 200
may have a copy made with a TestId of 225 or whatever number comes next in the identity sequence.
I would like to make it so that I now have control over creating the TestId. I would still like it to be unique of course but for copies I want something like a TestId of 200 to become 200-1 when copied.
Can someone give me a suggestion
as to how I can generate a unique number for the TestId inside my stored procedure instead of my using identity. I know
Oracle has sequences but is there anything like this with SQL Server and how could I use
them in a stored procedure?
SQL Server has sequences (starting with sql 2012).
http://msdn.microsoft.com/en-us/library/ff878091.aspx
You could also use an identity.
http://msdn.microsoft.com/en-us/library/ms186775.aspx
You probably don't want to do what you suggest as your desired solution. This is probably a better solution.
CREATE TABLE TEST
(
TestID int identity(1,1) not null
, OriginalID int not null
, MoreStuff ...
primary key (NewID)
)
You probably want an index on OriginalID too
And in your proc
Insert Into TEST (OrginalID, MoreStuff ...)
select TestID, MoreStuff ..
from Test from where TestID = #ID
Now you have a new test based on the original. And you can still refer back to the original based on OriginalID.
ADDED
This avoids somewhat messy logic that would be needed for you original suggestion. Now, if you must have a sequence 1,2,3 for each "based" test case, you can of course following your original suggestion (or a separate column for the inner sequence number). But don't do this unless you are forced to do so.

SQL-Statement with dynamic table-names or redesign?

I have a MS SQL 2008 database which stores data for creating a weighted, undirected graph. The data is stored in tables with the following structure:
[id1] [int] NOT NULL,
[id2] [int] NOT NULL,
[weight] [float] NOT NULL
where [id1] and [id2] represents the two connected nodes and [weight] the weight of the edge that connects these nodes.
There are several different algorithms, that create the graph from some basic data. For each algorithm, I want to store the graph-data in a separate table. Those tables all have the same structure (as shown above) and use a specified prefix (similarityALB, similaritybyArticle, similaritybyCategory, ...) so I can identify them as graph-tables.
The client program can select, which table (i.e. by which algorithm the graph is created) to use for the further operations.
Access to the data is done by stored procedures. As I have different tables, I would need to use a variable tablename e.g.:
SELECT id1, id2, weight FROM #tableName
This doesn't work because SQL doesn't support variable tablenames in the statement. I have searched the web and all solutions to this problem use the dynamic SQL EXEC() statement e.g.:
EXEC('SELECT id1, id2, weight FROM ' + #tableName)
As most of them mentioned, this makes the statement prone to SQL-injection, which I'd like to avoid. A simple redesign idea would be to put all the different graphs in one table and add a column to identify the different graphs.
[graphId] [int] NOT NULL,
[id1] [int] NOT NULL,
[id2] [int] NOT NULL,
[weight] [float] NOT NULL
My problem with this solution is, that the graphs can be very large depending on the used algorithm (up to 500 Million entries). I need to index the table over (id1, id2) and (id2, id1). Now putting them all in one big table would makes the table even huger (and requests slower). Adding a new graph would result in bad performance, because of the active indicees. Deleting a graph could not be done by TRUNCATE anymore, I would need to use
DELETE * FROM myTable WHERE graphId=#Id
which performs very bad with large tables and creates a very large logfile (which would exceed my disk space when the graph is big enough). So I'd like to keep the independent tables for each graph.
Any suggestions how to solve this problems by either find a way to parametrize the tablename or to redesign the database structure while avoiding the aforementioned problems?
SQL injection can easily be avoided in this case by comparing #tableName to the names of the existing tables. If it isn't one of them, it's bad input. (Obligatory xkcd reference: That is, unless you have a table called "bobby'; drop table students;")
Anyway, regarding your performance problems, with partitioned tables (since SQLServer 2005), you can have the same advantages like having several tables, but without the need for dynamic SQL.
Maybe I did not understand everything, but:
CREATE PROCEDURE dbo.GetMyData (
#TableName AS varchar(50)
)
AS
BEGIN
IF #TableName = 'Table_1'
BEGIN
SELECT id1
,id2
,[weight]
FROM dbo.Table_1
END
IF #TableName = 'Table_2'
BEGIN
SELECT id1
,id2
,[weight]
FROM dbo.Table_2
END
END
and then:
EXEC dbo.GetMyData #TableName = 'Table_1'
A different technique involves using synonyms dynamically, for example:
DECLARE #TableName varchar(50)
SET #TableName = 'Table_1'
-- drop synonym if it exists
IF object_id('dbo.MyCurrentTable', 'SN') IS NOT NULL
DROP SYNONYM MyCurrentTable ;
-- create synonym for the current table
IF #TableName = 'Table_1'
CREATE SYNONYM dbo.MyCurrentTable FOR dbo.Table_1 ;
IF #TableName = 'Table_2'
CREATE SYNONYM dbo.MyCurrentTable FOR dbo.Table_2 ;
-- use synonym
SELECT id1, id2, [weight]
FROM dbo.MyCurrentTable
Partioned Table may be the answer to your problem. I've got another idea, that's "the other way around":
each graph has it's own table (so you can still truncate table)
define a view (with the structured you mentioned for your redefined table) as a UNION ALL over all graph-tables
I have no idea of the performance of a select on this view and so on, but it may give you what you are looking for. I'd be interested in the results if try this out ..

Resources