I am looking for easy way to generate the DROP TABLE, CREATE TABLE and INSERT VALUES statements from a SELECT statement for my examples that I post on Stackoverflow.
I can normally get a SELECT statement to return a small subset of the data that I want to use as a sample. From there I would like a DROP TABLE, CREATE TABLE and INSERT VALUES to be generated.
Here is an example of the SELECT statement
SELECT ad.ApplicantDetailID,
ad.ApplicantMasterID,
ad.DateEffective,
ad.CorrespondenceTypeID,
ad.Value
FROM tblApplicantDetail AS ad
WHERE ad.CorrespondenceTypeID = 34
AND ad.ApplicantMasterID IN (41145,37046,45536,46764)
ORDER BY ad.ApplicantMasterID, ad.DateEffective
This SELECT statemenat returns 6 rows.
What I wouuld like a function to do is take a SELECT statement as input and generated the following TSQL Code (DROP TABLE, CREATE TABLE and INSERT VALUES). A second parameter can be used to send in a Temp Table name (i.e. in the example below #ApplicantDetail)
IF OBJECT_ID('tempdb..#ApplicantDetail') IS NOT NULL DROP TABLE #ApplicantDetail
CREATE TABLE #ApplicantDetail (
[ApplicantDetailID] [int] NOT NULL,
[ApplicantMasterID] [int] NOT NULL,
[DateEffective] [datetime] NOT NULL,
[CorrespondenceTypeID] [int] NOT NULL,
[Value] [varchar](20) NULL
)
GO
INSERT #ApplicantDetail VALUES (197542,37046,'2003-05-13 00:00:00.000',34,'8')
INSERT #ApplicantDetail VALUES (217963,41145,'1994-03-11 00:00:00.000',34,'')
INSERT #ApplicantDetail VALUES (217965,41145,'1994-03-21 00:00:00.000',34,'NS')
INSERT #ApplicantDetail VALUES (238961,45536,'2003-10-22 00:00:00.000',34,'')
INSERT #ApplicantDetail VALUES (238963,45536,'2003-12-03 00:00:00.000',34,'4')
INSERT #ApplicantDetail VALUES (244910,46764,'2003-12-03 00:00:00.000',34,'NS')
From there, I am hoping to just cut and paste the code generated to Stackoverflow.
This function will save me (an the Stackoverflow community) a lot of time when setting up some test data samples.
Since the #ApplicantDetail is created above you can use this SELECT statement in your example. It will return two records.
SELECT *
FROM #ApplicantDetail AS ad
WHERE ad.ApplicantMasterID = 45536
Maybe call the function GenerateSampleTSQLData.
Here is an idea on how the Function can look. I am not an expert on creating Functions so do change the syntax as needed.
GenerateSampleTSQLData('SELECT *
FROM #ApplicantDetail AS ad
WHERE ad.ApplicantMasterID = 45536',
'#AppDet')
I am running on SQL Server 2005 but will be upgrading to 2008.
If you can get it to run on one of them it would be great.
Now I am off to post another question that will actually use this sample data.
Thanks a bunch.
step 1..download SSMS Tools Pack (it is free) and install it http://www.ssmstoolspack.com/
step 2 run query
step 3 right click on result and select Script Grid Results (see image below)
Related
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.
I am trying to run the following merge statement to insert a row:
MERGE sales.Widget
USING (
VALUES ('19668651', 4.75))
AS widg (WidgetId, WidgetCost)
ON 1=0
WHEN NOT MATCHED THEN
INSERT (WidgetId, WidgetCost)
VALUES (widg.WidgetId, widg.WidgetCost)
OUTPUT INSERTED.WidgetId
INTO #inserted;
GO
I am confused by the error I am getting:
The column reference "inserted.WidgetId" is not allowed because it refers to a base table that is not being modified in this statement.
I thought that the inserted table was just an in-memory table of the values being passed in to the merge statement.
Why then would it care if I am modifying a "base" table as long as the value was passed in?
I can clearly tell that this is related to the fact that I have a view with an INSTEAD OF INSERT trigger on it (because it works fine against a normal table).
But why does SQL Server not just return the value that was passed in? (WidgetId in this case.)
Here is the script to reproduce the error:
CREATE SCHEMA sales
GO
-- Create the base table
CREATE TABLE sales.Widget_OLD(
WIDGET_ID int NOT NULL,
WIDGET_COST money NOT NULL
CONSTRAINT PK_Widget PRIMARY KEY CLUSTERED (WIDGET_ID ASC)
)
GO
-- Create the overlay view
CREATE VIEW sales.Widget AS
SELECT widg.WIDGET_ID AS WidgetId, widg.WIDGET_COST AS WidgetCost
FROM sales.Widget_OLD widg
GO
-- create the instead of insert trigger
CREATE TRIGGER sales.InsertWidget ON sales.Widget
INSTEAD OF INSERT AS
BEGIN
INSERT INTO sales.Widget_OLD (WIDGET_ID, WIDGET_COST)
SELECT Inserted.WidgetId, inserted.WidgetCost
FROM Inserted
END
GO
DECLARE #inserted TABLE (WidgetId varchar(11) NOT null);
MERGE sales.Widget
USING (
VALUES ('19668651', 4.75))
AS widg (WidgetId, WidgetCost)
ON 1=0
WHEN NOT MATCHED THEN
INSERT (WidgetId, WidgetCost)
VALUES (widg.WidgetId, widg.WidgetCost)
OUTPUT INSERTED.WidgetId
INTO #inserted;
GO
-- Clean up
DROP TRIGGER sales.InsertWidget
DROP VIEW sales.Widget
DROP TABLE sales.Widget_OLD
DROP SCHEMA sales
go
NOTE: This is from my Entity Framework Core application when I try to do 3+ inserts (see this question for more details) That question is about how to stop EF Core from using MERGE. This one is to understand what is happening.
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
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.
This question already has answers here:
Using merge..output to get mapping between source.id and target.id
(3 answers)
Closed 10 years ago.
The Situation:
I am inserting information from one table to another, a source and target. When the information is inserted into the target, a primary key is created. (In this case it is an integer.) I then need to be able to tie back to the source table. However, based on the data being moved, I am not able to reliably get the 1:1 match between the target and source tables.
The Question:
Is there a way to copy the primary key that was created for record(x) in the target table and copy it as a foreign key to that same record(x) in the source table as the bulk insert is happening?
Details:
I am trying to get this done in SQL. I have a work-around to this problem but I figure there has to be a way to do what I'm asking.
I found my answer after reading this great article.
http://sqlblog.com/blogs/adam_machanic/archive/2009/08/24/dr-output-or-how-i-learned-to-stop-worrying-and-love-the-merge.aspx
I acheived what I was looking for by using a MERGE and its OUTPUT clause. Here is my sample code that I used to figure this out.
I started by creating 3 temporary tables, #Temp2, #Temp3 and #Temp4. #Temp2 is considered the source table. #Temp3 would be the target table and #Temp4 is a bridge. I then inserted a few rows of very simple data, in this case just one field - Value.
CREATE TABLE #Temp2(
OldID INT IDENTITY(1,1),
Value INT,
NewFK INT)
CREATE TABLE #Temp3(
NewerID INT IDENTITY(1,1),
Value INT)
CREATE TABLE #Temp4(
OldID INT NOT NULL,
NewerID INT NOT NULL,
Value INT)
INSERT INTO #Temp2(Value)
VALUES(30), (40), (50), (70)
INSERT INTO #Temp3(Value)
VALUES (333), (444), (555), (777)
Then comes the MERGE statement that does the dirty work. It will be taking the value from #Temp2 and putting it into #Temp3. It will then take the ID created in #Temp3, the ID from #Temp2 and the Value that was passed, and throw them all into #Temp4.
MERGE INTO #Temp3 AS tgt
USING #Temp2 AS src
ON 1=0
WHEN NOT MATCHED THEN
INSERT(
Value)
VALUES(
src.Value)
OUTPUT
src.OldID,
INSERTED.NewerID,
src.Value
INTO #Temp4(OldID, NewerID, Value);
Then I ran an UPDATE to the staging table #Temp2 to update the NewFK field with the new ID. Lastly, do a simple SELECT to see the updated information.
UPDATE X
SET X.NewFK = Z.NewerID
FROM #Temp2 X
JOIN #Temp4 Z
ON X.OldID = Z.OldID
SELECT * FROM #Temp2
This acheived exactly what I needed and is a pretty streamlined way of doing things. I hope this will help some people who come across this question. Thanks everyone for your insight and responses.
NOTE:
I believe MERGE was introduced in SQL Server 2008.
Jonathan
One approach would be to set identity insert for your target table to 'on' (http://msdn.microsoft.com/en-us/library/ms188059.aspx). Then make that identity part of your 'source' data before you run the insert. Just remember to turn identity insert back off again once you're done.
EDIT
Not sure what your situation is, but one apporach I've taken in the past is to create a field to hold 'external source ID', just in case I needed to refer back to the source at some point in the future. In my case, this was for reference only, not normal transactional use.
If you can get a SharedExtPK in the target then this should work.
In this case logID is the PK of the source.
Tested:
DECLARE #MyTableVar table(
TargetPK int NOT NULL,
SourcePK int NOT NULL
);
INSERT INTO IdenOutPut (someValue, sharedExtKey)
OUTPUT INSERTED.iden,
INSERTED.sharedExtKey
INTO #MyTableVar
SELECT name, logID
FROM CatID
update sPK
set sPK.ExtPK = tTbl.TargetPK
FROM #MyTableVar as tTbl
JOIN CatID as sPK
on sPK.logID = tTbl.SourcePK
GO
If the values you insert are unique then could use that.
But it would get trickier.