I need to write procedure Textprocedure (Table_txt varchar(200)) that scans data from table My_table
For ex: I have table
My_table (Id int, Name varchar(200))
I need result of procedure execution like output text (script) like
DELETE FROM My_table
INSERT INTO My_table (Id, Name) values (1, 'Tropico')
INSERT INTO My_table (Id, Name) values (2, 'Bus')
INSERT INTO My_table (Id, Name) values (4, 'Africa')
INSERT INTO My_table (Id, Name) values (8, 'Arrival')
Can I do it with procedure? I do
CREATE TABLE My_table (Id int, Name varchar(200))
DELETE FROM My_table
INSERT INTO My_table (Id, Name) values (1, 'Tropico')
INSERT INTO My_table (Id, Name) values (2, 'Bus')
INSERT INTO My_table (Id, Name) values (4, 'Africa')
INSERT INTO My_table (Id, Name) values (8, 'Arrival')
ALTER PROCEDURE Textprocedure (#Table_txt varchar(200))
AS
BEGIN
DECLARE #Id1 NVARCHAR(40)
DECLARE #Result NVARCHAR(4000)
SET #Result = ''
SELECT #Result = 'INSERT INTO '+ CAST(#Table_txt AS NVARCHAR(250)) + --#Result
+'() values ' + CAST([name] AS NVARCHAR(250)) + ' ' FROM My_table --where Id<5
PRINT (#Result)
END
GO
EXEC Textprocedure My_table
My output: INSERT INTO My_table() values Arrival
But I need result in many rows. Can I do cycle? And I need print table params like id, name? But how can I pick them?
Check this to generate insert statements:
https://stackoverflow.com/a/982576/590741
http://vyaskn.tripod.com/code/generate_inserts.txt
You can use dynamic sql with parameters then print or return the result.
Related
There was a question here on SO that was since then removed. But while I was researching for ways to solve it, I was writing a script that avoids the use of an identity column and uses a sequence itself:
create table table1(Id int primary key, group_id int, Name varchar(64))
insert into table1(Id, group_id, Name) values (1, 1, 'a'), (2, 1, 'b'), (4, 1, 'c'), (8, 1, 'd')
declare #MaxId as int
select #MaxId = max(Id) + 1 from table1
declare #sql varchar(max)
set #sql = N'CREATE SEQUENCE MySequence AS INTEGER START WITH ' + cast(#maxId as varchar(10))
exec(#sql)
insert into table1(id, group_id, Name)
select next value for MySequence, 2, Name
from table1
where group_id = 1;
This actually works, that is, it successfully inserts four records with dynamically generated ids.
However, the the part of
declare #sql varchar(max)
set #sql = N'CREATE SEQUENCE MySequence AS INTEGER START WITH ' + cast(#maxId as varchar(10))
exec(#sql)
is very much counter-intuitive and hacky in my opinion.
Question: Is there a way to define a sequence that starts from a variable's value without generating a text and execute it?
The CREATE SEQUENCE syntax documentation shows a constant is required so you cannot specify a variable in the DDL statement.
Yes, creating a single-use dynamic sequence is a hack.
Instead use ROW_NUMBER(), something like
use tempdb
drop table if exists table1
go
create table table1(id int, group_id int, name varchar(200))
insert into table1(id,group_id,name) values (1,1,'a')
insert into table1(id,group_id,name) values (2,1,'a')
declare #maxValue int = (select max(id) from table1)
insert into table1(id, group_id, Name)
select #maxValue + row_number() over (order by Id), 2, Name
from table1
where group_id = 1;
select * from table1
Our reference tables each have a "Name" field with a unique index, plus an ID primary key. Is it possible to write a function like ID(#tableName varchar(100), #name varchar(100) that will return the ID? "EXEC" within functions does not seem to be allowed. If necessary we could specify that tables that this would work with inside the function.
Try using this approach (example for 2 simple tables)
CREATE TABLE Table1 (Id int, Name varchar(100));
INSERT INTO Table1 VALUES (1, 'Name1InTable1');
INSERT INTO Table1 VALUES (2, 'Name2InTable1');
INSERT INTO Table1 VALUES (3, 'Name3InTable1');
CREATE TABLE Table2 (Id int, Name varchar(100));
INSERT INTO Table1 VALUES (1, 'Name1InTable2');
INSERT INTO Table1 VALUES (2, 'Name2InTable2');
INSERT INTO Table1 VALUES (3, 'Name3InTable2');
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER FUNCTION dbo.f_GetIdFromTableByName
(
#tableName varchar(100), #name varchar(100)
)
RETURNS int
AS
BEGIN
DECLARE #Id int;
IF #tableName = 'Table1'
BEGIN
SELECT #Id = Id
FROM Table1
WHERE Name = #name;
END;
IF #tableName = 'Table2'
BEGIN
SELECT #Id = Id
FROM Table2
WHERE Name = #name;
END;
RETURN #Id
END
GO
Run function
SELECT dbo.f_GetIdFromTableByName('Table2','Name2InTable2')
I want to execute a stored procedure only once but pass different parameter values every time from the temp table #tbl_schools. How can I accomplish this task?
create table #tbl_schools(id int not null)
insert into #tbl_schools(id) values (1)
insert into #tbl_schools(id) values (2)
insert into #tbl_schools(id) values (3)
insert into #tbl_schools(id) values (4)
insert into #tbl_schools(id) values (5)
insert into #tbl_schools(id) values (6)
insert into #tbl_schools(id) values (7)
select * from #tbl_schools nolock
go-----------
create proc sp_Prac #id int
as
print 'ID is: ' + cast(#id as varchar(10)) + char(10)
go-----------
exec sp_Prac #id = select id from #tbl_schools -- This part errors out.
Try this Answer:
CREATE TABLE #tbl_schools(id INT NOT NULL)
INSERT INTO #tbl_schools(id) VALUES (5)
INSERT INTO #tbl_schools(id) VALUES (13)
INSERT INTO #tbl_schools(id) VALUES (1)
INSERT INTO #tbl_schools(id) VALUES (7)
INSERT INTO #tbl_schools(id) VALUES (2)
INSERT INTO #tbl_schools(id) VALUES (8)
INSERT INTO #tbl_schools(id) VALUES (4)
SELECT * FROM #tbl_schools NOLOCK
GO-----------
CREATE PROC sp_Prac #id INT
AS
PRINT 'ID is: ' + CAST(#ID AS VARCHAR(10)) + CHAR(10)
GO-----------
DECLARE #MAX INT, #MIN INT, #CurValue INT
SELECT *,ROW_NUMBER() OVER(ORDER BY id)RN
INTO #MyTable
FROM #tbl_schools
SELECT #MAX=MAX(RN),#MIN=MIN(RN) FROM #MyTable
WHILE #MIN<=#MAX
BEGIN
SELECT #CurValue=ID FROM #MyTable WHERE RN=#MIN
EXEC sp_Prac #id = #CurValue
SET #MIN=#MIN+1
END
DROP TABLE #tbl_schools
DROP TABLE #MyTable
Result:
ID is: 1
ID is: 2
ID is: 4
ID is: 5
ID is: 7
ID is: 8
ID is: 13
Just for simplicity suppose I have two tables
user table (id, email)
user log table (id, date)
whatever id gets inserted in user table, same id should be inserted in user_log table also else transaction should fail.
How can I do this
BEGIN TRANSACTION
INSERT into user(id, email) OUTPUT Inserted.id (1, 'a#x.com', 'x'), (2, 'b#x.com', 'y')
// I also want to be able to do
INSERT into user_log(id, date) values(1, date), (2, date)
COMMIT TRANSACTION
You can insert the output directly into the user_log table:
BEGIN TRANSACTION
INSERT INTO [User] (ID, Email)
OUTPUT inserted.id, CURRENT_TIMESTAMP INTO user_log(id, date)
VALUES (1, 'a#x.com'), (2, 'b#x.com');
COMMIT TRANSACTION
Example on SQL Fiddle
If you need to return the ids you can just add a second OUTPUT clause:
BEGIN TRANSACTION
INSERT INTO [User] (ID, Email)
OUTPUT inserted.id, CURRENT_TIMESTAMP INTO user_log(id, date)
OUTPUT inserted.id
VALUES (1, 'a#x.com'), (2, 'b#x.com');
COMMIT TRANSACTION
Method 1 - "Double Insert" using OUTPUT
Pros: single statement, no hidden triggers (method 2).
Cons: only works in this statement i.e. doesn't capture all insert events
INSERT INTO dbo.users (id)
OUTPUT inserted.id
INTO user_log (id)
VALUES (9)
, (3)
, (7)
;
Method 2 - Trigger
Pros: Captures all insert events
Cons: Triggers are "hidden" mechanisms
CREATE TRIGGER user_log_after_insert
ON dbo.users
AFTER INSERT
AS
BEGIN
INSERT INTO dbo.user_log (id)
SELECT id
FROM inserted
;
END
;
Method 3 - Temp Table
Included for completeness for when using older versions of SQL Server that don't support method 1
CREATE TABLE #temp (
id int
);
INSERT INTO #temp (id) VALUES (9);
INSERT INTO #temp (id) VALUES (3);
INSERT INTO #temp (id) VALUES (7);
BEGIN TRAN
INSERT INTO dbo.users (id)
SELECT id
FROM #temp
;
INSERT INTO dbo.user_log (id)
SELECT id
FROM #temp
;
COMMIT TRAN
In php I'm executing multiple queries at once, the queries are wrote in one big variable.
These are insert queries and I have to retrieve each autoincrement "id" of the records created in the db. How to do it ?
The results set retrieved don't seems to keep each single result but just one.
I think that you are talking about an OUTPUT clause from the insert statement.
http://msdn.microsoft.com/en-us/library/ms177564.aspx
CREATE TABLE #t (id int identity (1, 1), f1 nvarchar(20 ) ) --the table that has the identities
CREATE TABLE #ids ( id int ) --the table to store the inserts into table #t
INSERT INTO #t ( f1 ) OUTPUT INSERTED.id INTO #ids SELECT N'AAAA'
INSERT INTO #t ( f1 ) OUTPUT INSERTED.id INTO #ids SELECT N'BBBB'
INSERT INTO #t ( f1 ) OUTPUT INSERTED.id INTO #ids SELECT N'CCCC'
SELECT * FROM #t
SELECT * FROM #ids
Another way is to use ##IDENTITY or SCOPE_IDENTITY() SQL Authority link discussing/comparing them
CREATE TABLE #t (id int identity (1, 1), f1 nvarchar(20 ) )
CREATE TABLE #ids ( id int )
INSERT INTO #t ( f1 ) SELECT N'AAAA'
INSERT INTO #ids SELECT ##IDENTITY --OR you can use SELECT SCOPE_IDENTITY()
INSERT INTO #t ( f1 ) SELECT N'BBBB'
INSERT INTO #ids SELECT ##IDENTITY --OR you can use SELECT SCOPE_IDENTITY()
INSERT INTO #t ( f1 ) SELECT N'CCCC'
INSERT INTO #ids SELECT ##IDENTITY --OR you can use SELECT SCOPE_IDENTITY()
SELECT * FROM #t
SELECT * FROM #ids