sql create database from variable - sql

I have #db_out = 'aux.dbo.some_table_name' , and I don't know how to drop , create based on that variable like :
IF OBJECT_ID(#db_out) IS NOT NULL DROP TABLE "#db_out" - not working
CREATE TABLE "#db_out" .... etc
it creates master.dbo.#dbo_out
How can I use that variable to create that table or verify it and drop it ?

You will have to build the statement in varchar variable and execute it:
declare #strSql as varchar(max)
IF OBJECT_ID(#db_out) IS NOT NULL
BEGIN
EXEC ('DROP TABLE [' + #db_out + ']')
END
set #strSql = 'CREATE TABLE [' + #db_out + '] (' -- Etc
EXEC (#strSql)

You need to write dynamic SQL.
SET #sql = 'IF OBJECT_ID(#db_out) IS NOT NULL DROP TABLE ' + #db_out + '; '
SET #sql = #sql + 'CREATE TABLE ' + #db_out + ' (...)'
EXEC(#sql)

Related

Add new column to all tables in database

I'm trying to figure out if there's a quick way or single query to add a new column to all tables in database.
Right now I'm doing this for each table
ALTER TABLE [dbo].[%TABLE_NAME%] ADD %COLUMN_NAME% DATATYPE NOT NULL DEFAULT %VALUE%;
Is there a procedure or query I can make in AzureDataStudio to add a new column to all tables with the same name and default value.
select 'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME([schema_id])) + '.' + QUOTENAME([name])
+ ' ADD %COLUMN_NAME% DATATYPE NOT NULL DEFAULT %VALUE%;'
from sys.tables
Create the statements you need with the above then run them.
I'd personally create a loop with dynamic SQL which gets executed as it is ran. The code below creates a temp table which is utilized for the loop which will iterate through each table listed in the temp table based on a calculated row number. The dynamic SQL is then set and executed.
Once you make the necessary changes, putting in your database name, column name, data type, and default value and you are satisfied with the results that get printed, you can un-comment the EXECUTE(#SQL) and re-run the script and it will add the new column to all your tables.
USE [INSERT DATABASE NAME HERE]
GO
IF OBJECT_ID(N'tempdb..#TempSysTableNames') IS NOT NULL
BEGIN
DROP TABLE #TempSysTableNames
END;
DECLARE #ColumnName VARCHAR(250) = 'INSERT COLUMN NAME HERE'
,#DataType VARCHAR(250) = 'INSERT DATA TYPE HERE'
,#DefaultValue VARCHAR(250) = 'INSERT DEFAULT VALUE HERE'
,#SQL VARCHAR(8000)
,#MaxRowNum INT
,#I INT = 1;
SELECT '[' + DB_NAME() + '].[' + OBJECT_SCHEMA_NAME([object_id],DB_ID()) + '].[' + name + ']' AS [name]
,ROW_NUMBER() OVER (ORDER BY [create_date]) AS RowNum
INTO #TempSysTableNames
FROM sys.tables
WHERE [type] = 'U';
SET #MaxRowNum = (SELECT MAX(RowNum)
FROM #TempSysTableNames);
WHILE (#I <= #MaxRowNum)
BEGIN
SET #SQL = (SELECT 'ALTER TABLE ' + [name] + ' ADD ' + #ColumnName + ' ' + #DataType + ' NOT NULL DEFAULT ' + #DefaultValue + ';'
FROM #TempSysTableNames
WHERE RowNum = #I);
PRINT(#SQL);
--EXECUTE(#SQL);
SET #I += 1;
END;

Compare single values in SQL to identify candidate keys [duplicate]

This question already has answers here:
SQL Server: Get table primary key using sql query [duplicate]
(10 answers)
How to find out whether a table has some unique columns
(5 answers)
Closed 6 years ago.
I need to check if a column is candidate key. To make it generic, I created a stored procedure:
ALTER PROCEDURE [dbo].[CheckPK]
(
#tableName VARCHAR(100),
#pk VARCHAR(100)
)
AS
PRINT 'Checking for candidate key ' + #pk + ' for table: ' + #tableName
DECLARE #sql NVARCHAR(4000)
SET #sql = 'select count(distinct ([' + #pk + '])) as tot_pk from ' + #tableName + ' select count (*) as tot_real from ' + #tableName
EXEC sp_executesql #sql
Which works fine. What I have to do is verify that the two selected values are the same.
QUESTION: is it possible to add an if(tot_pk = tot_real) type of condition?
I am a newbie in SQL, so I apologise if this question seems trivial. Thank you
Try this code. Maybe is that you need.
I added an optional parameter #Schema.
CODE
--EXEC [dbo].[CheckPK] 'name of table','name of column', 'schema is optional'
ALTER PROCEDURE [dbo].[CheckPK]
(
#tableName VARCHAR(100)
, #pk VARCHAR(100)
, #Schema VARCHAR(100) = NULL
)
AS
BEGIN
BEGIN TRY
PRINT 'Checking primary key ' + #pk + ' for table: ' + #tableName
DECLARE #sql NVARCHAR(4000)
SET #sql = 'select count(distinct ([' + #pk + '])) as tot_pk from '
+ ISNULL(#Schema + '.', '') + #tableName + ' select count (*) as tot_real from ' + ISNULL(#Schema + '.', '') + #tableName
EXEC sp_executesql #sql
IF EXISTS (
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + CONSTRAINT_NAME), 'IsPrimaryKey') = 1
AND TABLE_NAME = #tableName
AND TABLE_SCHEMA = ISNULL(#Schema, TABLE_SCHEMA)
AND COLUMN_NAME = #pk
)
SELECT #pk + ' IS A PRYMARY KEY'
ELSE
SELECT #pk + ' IS NOT A PRYMARY KEY'
END TRY
BEGIN CATCH
SELECT 'An error has occurred. Verify that ''' + #tableName + ''' it is a table and has the correct schema and ''' + #pk + ''' is a valid column of the table'
END CATCH
END

What is the most efficient SQL query to Append Data to a master table?

I have a master table with ~400M records, on a weekly basis I append ~1.5M records to the table.
I am currently using a simple INSERT INTO query, but i'm not sure if that's the most efficient.
For example:
Insert INTO MasterTbl Select * FROM NewData
It would take hours just to insert this one table.
Any help appreciated, thank you.
There's no magic bullet that fits every situation. Here's are something that I've tried in teh past:
Use BULK INSERT, which bypasses the transaction log. See Robert Sheldon's article.
Drop all indices prior to the insert operation. You can recreate them after.
Minimize logging, also covered by Robert Sheldon
Best is to use Partition table. On a weekly basis run a stored procedure that will create a new partition based on date.
I had a scenario where I had to delete millions of rows so I used partition table to efficiently delete it. In your case on a weekly basis you will switch out a partition table to the master table.
Here is the stored proc I used to run to take care of my partition, you could come up with something similar.
CREATE TYPE [dbo].[RollingTablePartitionWorkTableType] AS TABLE
(
[PartitionDate] [DATE] NOT NULL PRIMARY KEY,
[Operation] [varchar](3) NULL -- add, del, nop
)
CREATE PROCEDURE [dbo].[ProcessPartitionWorkTable]
#PartitionTable SYSNAME,
#TableSchema SYSNAME,
#PartitionWorkTable [dbo].[RollingTablePartitionWorkTableType] READONLY
AS
DECLARE #sql nvarchar(max);
DECLARE #PartitionDate date, #Operation VARCHAR(3);
DECLARE PartitionWorkTableCursor CURSOR LOCAL READ_ONLY FOR
SELECT PartitionDate, Operation FROM #PartitionWorkTable ORDER BY PartitionDate ASC;
OPEN PartitionWorkTableCursor;
DECLARE #IsAdded bit = 0;
DECLARE #DateString NVARCHAR(100);
FETCH NEXT FROM PartitionWorkTableCursor
INTO #PartitionDate, #Operation;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #DateString = '''' + cast(#PartitionDate as NVARCHAR(100)) + '''';
IF #Operation = 'add'
BEGIN
SET #IsAdded = 1; -- Changing the retention period will cause partitons to be added and merged. This flag is set to avoid deleting data during partition merge.
SET #sql = N'ALTER PARTITION SCHEME ' + #PartitionTable + N'_RPScheme NEXT USED [PRIMARY];'
exec ( #sql );
SET #sql = N'ALTER PARTITION FUNCTION ' + #PartitionTable + N'_RPFunction () SPLIT RANGE (' + #DateString + ');';
exec ( #sql );
END
ELSE IF #Operation = 'del'
BEGIN
IF #IsAdded = 0
BEGIN
SET #sql = N'TRUNCATE TABLE ' + #PartitionTable + N'_Delete;'
EXEC ( #sql );
SET #sql = N'ALTER TABLE ' + #TableSchema + '.' + #PartitionTable + ' SWITCH PARTITION 1 TO ' + #PartitionTable + N'_Delete;';
EXEC ( #sql );
SET #sql = N'TRUNCATE TABLE ' + #PartitionTable + N'_Delete;'
EXEC ( #sql );
END
SET #sql = N'ALTER PARTITION FUNCTION ' + #PartitionTable + N'_RPFunction () MERGE RANGE (' + #DateString + ');';
exec ( #sql );
IF #IsAdded = 0
BEGIN
SET #sql = N'ALTER TABLE ' + #TableSchema + '.' + #PartitionTable + ' SWITCH PARTITION 1 TO ' + #PartitionTable + N'_Delete;';
EXEC ( #sql );
SET #sql = N'TRUNCATE TABLE ' + #PartitionTable + N'_Delete;'
EXEC ( #sql );
END
END
FETCH NEXT FROM PartitionWorkTableCursor
INTO #PartitionDate, #Operation;
END;
CLOSE PartitionWorkTableCursor;
DEALLOCATE PartitionWorkTableCursor;
RETURN 0

Generate string processing for on rows from some table

I've got table with columns and procedure to create SQL table:
DECLARE #SQLString NVARCHAR(MAX)
SELECT #SQLString =
'
'+ ColName + ' ' + ColType + ' '+ ColNullable + ',
'
FROM FS_Report_Tables WHERE TableId = 0
PRINT ('CREATE TABLE '+ 'Test' + #SQLString)
EXEC ('CREATE TABLE '+ 'Test' + #SQLString)
Current code prints only last column when I need all ( without coma at last )
Data table example:
ColumnId TableId ColName ColType ColNullable
1 0 A int NOT NULL
2 0 B int NOT NULL
How can I build SQLString with nodes from SELECT from another table?
Please try:
DECLARE #SQLString NVARCHAR(MAX)
SELECT
#SQLString = COALESCE(#SQLString + ', ', '') + ColName + ' ' + ColType + ' ' + ColNullable
from
YourTable
select #SQLString
EXEC ('CREATE TABLE YourTableName (' + #SQLString + ')')
DECLARE #SQLString NVARCHAR(MAX)
SET #SQLString = 'CREATE TABLE '+ #TableName +
'
( '+#Column1Name+' '+#Column1DataType +' '+#Column1Nullable +')
'
PREPARE stmt FROM #SQLString;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You need to use prepared statements
SQL server provides you a stored procedure, sp_executesql which will do this task for you

How can I copy a row into same table with SQL Server 2008

A) My way so far:
sqlCommand.CommandText =
"INSERT Table1 ([column1],[column2],[column3])" +
" SELECT [column1],[column2],[column3]" +
" FROM Table1 WHERE Id =" + param +
";select scope_identity() as id";
B) I wish to do something like this:
INSERT INTO "table1" (* (without the ID-column))
SELECT (* (without the ID-column))
FROM "table1"
Note: I'm copying to the same table. I just want to easy copy it all to another row, while ofcourse giving the new row a new ID.
Is that good practice and possible or not?
I had the same issue myself and wanted a nice and simple way of doing this.
I found a solution here which allows this. I've modified it slightly to remove the output id and also to make the IdColumnName have a default value of 'Id'.
IF OBJECT_ID('TableRowCopy') IS NOT NULL DROP PROCEDURE TableRowCopy
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[TableRowCopy](
#TableName VARCHAR(50),
#WhereIdValue INT,
#IdColumnName VARCHAR(50) = 'Id'
)
AS
BEGIN
DECLARE #columns VARCHAR(5000), #query VARCHAR(8000);
SET #query = '' ;
SELECT #columns =
CASE
WHEN #columns IS NULL THEN column_name
ELSE #columns + ',' + column_name
END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (
TABLE_NAME = LTRIM(RTRIM(#TableName))
AND
column_name != LTRIM(RTRIM(#IdColumnName))
);
SET #query = 'INSERT INTO ' + #TableName + ' (' + #columns + ') SELECT ' + #columns + ' FROM ' + #TableName + ' WHERE ' + #IdColumnName + ' = ' + CAST(#WhereIdValue AS VARCHAR);
EXEC (#query);
SELECT SCOPE_IDENTITY();
END
Example usage:
EXEC TableRowCopy 'MyTable', 3
The only way of doing this is to list all the columns out as in your first example. There is no syntax like SELECT *, -Id
You should use parameterised SQL though for SQL injection and plan caching reasons.