SQL Select table name - sql-server

A database had has 4 tables that has the same columns EG. SalesJAn, SalesFeb, SalesMarch, SalesApril.
I want to run a query in SQL server or in report builder Where i can change the table name based on a selection which one of 4 tables will be queried . Eg Filter in report builder
Like this
declare #tablename varchar(50)
set #tablename = 'test'
select * from #tablename

You can create a procedure which will do a select for a given table name. This procedure could look like this:
CREATE PROCEDURE EXECUTE_SELECT
#tbl sysname
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = N' SELECT * FROM ' + QUOTENAME(#tbl)
EXECUTE sp_executesql #SQL
END
Then you can execute this procedure for every table name you want. Please see here an example according to your description: db<>fiddle
If this doesn't help you, please point out which exactly you still need to know. Thank you.

Related

How to pass schema name as parameter in SQL Server stored procedure?

As I have seen so far, people suggested using dynamic SQL.
For example:
How to pass schema as parameter to a stored procedure in sql server?
How to pass schema name as parameter in stored procedure
However, dynamic SQL has the risk of SQL injection. Hence, I want to know if there are any other safe alternatives?
Basically, this stored procedure that I am creating will be called at runtime. There will be 2 possible schemas to be passed in. And the table name will be passed in as well.
Something like below: (It does not work)
CREATE PROCEDURE [EFM].[usp_readApexTable]
#SCHEMANAME VARCHAR(20) = NULL,
#TABLENAME VARCHAR(100) = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM [#SCHEMANAME].[#TABLENAME];
END
GO
This is just an example of READ action. My plan is to create for CRUD, which requires 4 different stored procedures.
You can use QUOTENAME to avoid any SQL injection and build your dynamic query like the following:
CREATE PROCEDURE [EFM].[usp_readApexTable]
#SCHEMANAME VARCHAR(20) = NULL,
#TABLENAME VARCHAR(100) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL VARCHAR(MAX)=N'SELECT * FROM '
+ QUOTENAME(#SCHEMANAME) + '.' + QUOTENAME(#TABLENAME)
EXEC (#SQL)
END
GO
Note: If you have any plan to add parameters also for your WHERE clause, in that case QUOTENAME will not help much, I suggest to to use sp_executesql by passing appropriate parameters used in WHERE clause.
Still you need to use QUOTENAME for schema and table name as SQL excepts it only as literal, you can't use variable names for table and schema.
For example.
declare #sql nvarchar(max)
set #sql = N'select * from ' + quotename(#SCHEMANAME ) + '.' + quotename(#TABLENAME )
+ ' where (City = #City)'
exec sp_executesql
#sql,
N'#City nvarchar(50)',
#City
You can find more details here
You need to use dynamic sql to do this operation
CREATE PROCEDURE [EFM].[usp_readApexTable]
#SCHEMANAME VARCHAR(20) = NULL,
#TABLENAME VARCHAR(100) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sqlCommand nvarchar(MAX)
SET #sqlCommand='SELECT * FROM ['+#SCHEMANAME+'].['+#TABLENAME+'];'
--Create Your Temp Table where you can set the records after executing the dynamic query
CREATE TABLE #tmpTbl(
Column1 [datatype]
Column2 [datatype]
.
.
ColumnN
)
INSERT INTO #tmpTbl EXEC sp_executesql #sqlCommand --Copy data to #tmpTbl table
SELECT * FROM #tmpTbl
DROP TABLE #tmpTbl
END
GO

Stored Procedure in sql for selecting columns based on input values

I am trying to code a stored procedure in SQL that does the following
Takes 2 inputs (BatchType and "Column Name").
Searches database and gives the batchdate and the data in the column = "Column name"
Code is as give below
ALTER PROCEDURE [dbo].[chartmilldata]
-- Add the parameters for the stored procedure here
(#BatchType nvarchar (50),
#Data nvarchar(50))
AS
BEGIN
-- Insert statements for procedure here
SELECT BatchDate,#Data FROM --Database-- WHERE BatchType = #BatchType
END
I am trying to select column from the database based on operator input. But I am not getting the output. It would be great if someone can give me a direction.
You may want to build out your SELECT statement as a string then execute it using sp_executesql.
See this page for more info:
https://msdn.microsoft.com/en-us/library/ms188001.aspx
This will allow you to set your query to substitute in your column name via your variable and then execute the statement. Be sure to sanitize your inputs though!
You'd need to use dynamic SQL, HOWEVER I would not recommend this solution, I don't think there is anything I can add as to why I wouldn't recommend it that isn't explained better in Erland Sommarskog in The Curse and Blessings of Dynamic SQL.
Nonetheless, if you had to do it in a stored procedure you could use something like:
ALTER PROCEDURE [dbo].[chartmilldata]
-- Add the parameters for the stored procedure here
(#BatchType nvarchar (50),
#Data nvarchar(50))
AS
BEGIN
-- DECLARE AND SET SQL TO EXECUTE
DECLARE #SQL NVARCHAR(MAX) = N'SELECT BatchDate = NULL, ' +
QUOTENAME(#Data) + N' = NULL;';
-- CHECK COLUMN IS VALID IN THE TABLE
IF EXISTS
( SELECT 1
FROM sys.columns
WHERE name = #Data
AND object_id = OBJECT_ID('dbo.YourTable', 'U')
)
BEGIN
SET #SQL = 'SELECT BatchDate, ' + QUOTENAME(#Data) +
' FROM dbo.YourTable WHERE BatchType = #BatchType;';
END
EXECUTE sp_executesql #SQL, N'#BatchType NVARCHAR(50)', #BatchType;
END
It would probably be advisable to change your input parameter #Data to be NVARCHAR(128) (or the alias SYSNAME) though, since this is the maximum for column names.

How to SELECT * into a SQL table incremntally by date?

I have a SQL Server table called "tblProducts".
Sometimes I backup this table by making a copy of it with this simple query:
SELECT *
INTO [test01].[dbo].[tblProducts_20141206]
FROM [test01].[dbo].[tblProducts]
Every time when making a backup, the date is included in the table name.
I would like to create a SQL Job that runs this kind of query once every week.
Is it possible to maybe in a stored procedure or declaring a variable to achieve this that allows the backed-up table name to be named like [tblProducts_todaysDate]?
Thanks.
If you are using a SP, you can do something like:
CREATE PROC sp_createATable
#name VARCHAR(20) AS
CREATE TABLE #name
...
do your insert
Or, if you want to, w/o SP:
DECLARE #name varchar(20)
SET #name = 'tblName' + SELECT CONVERT(VARCHAR(8), GETDATE(), 112) AS [YYYYMMDD]
CREATE TABLE #name
...
do your insert
You need Dynamic SQL to create the tables names appended with date.
CREATE PROC usp_createtable( #tablename VARCHAR(20),
#Dbname VARCHAR(20),
#SchemaName VARCHAR(20))
AS
BEGIN
DECLARE #sql NVARCHAR(max)
SET #sql =' SELECT * INTO '+#Dbname+'.'+#SchemaName+'.'+#tablename+'CONVERT(VARCHAR(8), GETDATE(), 112) FROM '+#Dbname+'.'+#SchemaName+'.'+#tablename''
EXEC sp_executesql
#sql
END

SQL Server Select-Into stored procedure

I am trying to write a custom stored procedure to carry out a select into operation. I want to copy a table (or some columns from a table) from one database to another. I am using SQL Server 2012
CREATE Procedure select_into
AS
Begin
#selection varchar(128),
#newtabname varchar(128)
#fromtabname varchar(128)
Select selection,
INTO table1,
FROM table2,
WHERE selection = #selection AND table1 = #newtabname AND table2 =#fromtabname;
go
EXEC select_into, Ecode, relational_db.dbo.work, dbo.Work_Data;
I get an error message indicating a syntax error near the "." in relational_db.dbo.work.
I would appreciate any help in getting this right
You have a missing comma in parameter list and wrong syntax for procedure declaration. It should be::
CREATE Procedure select_into
(
#selection varchar(128),
#newtabname varchar(128),
#fromtabname varchar(128)
)
AS
Begin
BUT, in addition your syntax for an INSERT INTO contains extra commas and you cannot perform dynamic T-SQL that way.
Can I suggest you first learn TSQL's syntax for SQL Server.
Try something like this ...
CREATE Procedure select_into
#selection NVARCHAR(128),
#newtabname NVARCHAR(128),
#fromtabname NVARCHAR(128)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'Select ' + QUOTENAME(#selection) +
N' INTO ' + QUOTENAME(#newtabname) +
N' FROM ' + QUOTENAME(#fromtabname)
EXECUTE sp_executesql #sql
END

Replace first FROM in sql query

I need to write a query engine on a web app, what needs to be accomplish is that a user can enter any SELECT statement into a textbox and then the results should be created into a new table.
This is my function I have created but it only support SQL Server 2012 and I want similar to this function but only it should support SQL Server 2005 and above:
CREATE FUNCTION [dbo].[CustomQueryTableCreation]
(
#TableName varchar(max),
#sql NVARCHAR(MAX)
)
RETURNS
#TableBuilder TABLE
(
DS varchar(max)
)
BEGIN
INSERT INTO #TableBuilder
SELECT 'CREATE TABLE dbo.' + #TableName+'(';
INSERT INTO #TableBuilder
SELECT
CASE column_ordinal
WHEN 1 THEN '' ELSE ',' END
+ name + ' ' + system_type_name + CASE is_nullable
WHEN 0 THEN ' not null' ELSE '' END
FROM
sys.dm_exec_describe_first_result_set
(
#sql, NULL, 0
) AS f
ORDER BY
column_ordinal;
INSERT INTO #TableBuilder
SELECT ');';
RETURN
END
What I want to do now is that I want to search through my query and replace the FIRST FROM with INTO NewTable FROM.
The query can contain multiple joins.
Should I control this with SQL or C#?
I had a similar problem with the 2005 Environment. If you save the Select query to a table, and use the following built in procedure to execute the query:
EXECUTE sp_executesql #Query
Here is the MS docs:
http://msdn.microsoft.com/en-us/library/ms188001%28v=sql.90%29.aspx
Edit
Keeping this in mind, can take the SQL dumps and Create OpenRowset Queries to take the SQL and dump them into a TempTable, and from the Temp Table to a permanent table if required.
I created the following SP's to assist with getting the info to a permanent table.
First the procedure to execute the specific SQL Statement
CREATE PROCEDURE [dbo].[spExecuteRowset]
(
#Query NVARCHAR(MAX)
)
AS
BEGIN
--Execute SQL Statement
EXECUTE sp_executesql #Query
END
Then the OpenRowset SP:
CREATE PROCEDURE [dbo].[spCustomquery]
(
#ProQuery NVARCHAR(MAX),
#Tablename NVARCHAR(MAX)
)
AS
BEGIN
--Insert the info into a Specidied Table
DECLARE #Query NVARCHAR(max)
SET #Query = 'SELECT * INTO #MyTempTable FROM OPENROWSET(''SQLNCLI'', ''Server=localhost;Trusted_Connection=yes;'','' EXEC [YOUR DATABASE].dbo.spExecuteRowset' +''''+#ProQuery+''''') SELECT * INTO '+ #Tablename +' FROM #MyTempTable'
--FOR DEBUG ONLY!!!!
PRINT #Query
EXEC [YourDatabase].dbo.spExecuteRowset #Query
END
This takes it from the #tempTable to A Physical Table.
Here are some docs on OpenRowset.
You have no guarantee that the first from in a query will accept an into, because you can have a subselect in the select statement. In addition, you could have a field name like datefrom that throws things off too.
But, assuming you have "simple" SQL statements, you can do it as:
select stuff(#query, charindex('from ', #query), 0, 'into '+#Table+' ')
from t;
EDIT:
The following is what you really want to do:
select *
into #Table
from (#query) q;
Using the subquery solves the problem.
This is a well-known problem. String concatenation is usually a bad/limited solution.
The more recommended solution is to let some other mechanism to return you the result set (openquery etc.), and then insert it to a table.
For example:
SELECT *
INTO YourTable
FROM OPENQUERY([LinkedServer],your query...)

Resources