Select values from SQL table - leave specific column names (name condition) - sql-server

I have SQL table like this:
create table [Tbl](
[_Id] int Identity(1, 1),
[_ProjectId] int,
[Name] varchar(255),
[Age] int
...
Primary Key([_Id])
)
I need to select all values but not from the columns which names started by "_" (_Id, _ProjectId). How can I do it?
(For understanding: I have many tables like this with their specific columns. I don't know all the colum names).

You list the columns you want in the column list of your query. Don't add the columns that begins with a _.
Update:
You can build the query dynamically in for example a stored procedure where you have table name as a parameter. Use the sys.columns to get the column names and exclude the columns you don't want.
create procedure YourProcedure
#TableName sysname
as
declare #SQL nvarchar(max)
set #SQL = '
select '+stuff((select ','+quotename(name)
from sys.columns
where object_id = object_id(#TableName) and
left(name, 1) <> '_'
for xml path(''), type).value('text()[1]', 'sysname'),1,1,'')+'
from '+quotename(#TableName)
exec sp_executesql #SQL
SQL Fiddle

You can't use wildcards on column names.
Either select all with
select * from table
or specify which columns you want to select witt their full name
select name, age from table

List the columns you want separated by commas , instead of *
SELECT Name, Age, Col3, Col4, ColN FROM Tb1

Related

SQL: I want to extract data from second table. As column names of second table matches with values Separated by comma of first table column

I have a table1 with one column with values seperated by comma firstname,lastname. I have a table2 with two column names firstname and lastname, which match with table1's single column values(firstname,lastname). My necessity is I want to extract data from table2 by using select statement SELECT firstname,lastname FROM table2. I used variables to write query.
I transferred values of table1(firstname, lastname) to #link variable and this operation completed successfully. But when i tried to add SELECT #link FROM table2 to the query i thought i would get data of firstname and lastname of table2, But result showing a seperate no column name and value in that column as firstname,lastname.
Tons of Thanks for any help!
declare #link nvarchar(max)
select #link = (select [column]
from [dbo].[table1])
from [dbo].[table2]
SELECT #link FROM table2
You appear to be attempting "dynamic sql", i.e. you build a string that contains a select statment, then execute that string as a query. Conventionally you will find many example that use #sql for this, and the basic fom of this is as follows:
declare #sql nvarchar(max)
select #sql = N'select [column] from [dbo].[table1]'
EXEC sp_executesql #sql;
Note that the #sql contents has to be valid sql syntax. On this point your code contains 2 from clauses and that is NOT valid, plus it isn't clear what you intended, perhaps it was meant to be a join.
declare #sql nvarchar(max)
select #sql = N'select t.[column], j.[column2]
from [dbo].[table1] as t
inner join [dbo].[table2] as j on t.id = j.fk'
EXEC sp_executesql #sql;

Join a table whose name is stored in the first table

I have a first table [TABLE1] with columns [ID], [Description], [DetailTable]. I want to join [TABLE1] with the [DetailTable]. The name of [DetailTable] is stored in [TABLE1] column.
"SELECT * FROM TABLE1 CROSS JOIN ?????"
Any suggestions?
So... if you cheat and SELECT * from the detailtab, you could do something a bit like this, with dynamic SQL:
-- For the example, choose either 1 or 2 to see the #foo table or the #bar table
DECLARE #Id INT = 1
-- EXAMPLE SCENARIO SETUP --
CREATE TABLE #ListOfTables
( ID INT IDENTITY(1,1) NOT NULL
,[Description] NVARCHAR(255) NOT NULL
,[DetailTable] NVARCHAR(255) NOT NULL);
CREATE TABLE #foo
(Foothing VARCHAR(20));
CREATE TABLE #bar
(Barthing VARCHAR(20));
-- TEST VALUES --
INSERT #ListOfTables VALUES ('foo','#foo'),('bar','#bar');
INSERT #foo VALUES ('A foothing Foothing');
INSERT #bar VALUES ('A barthing Barthing');
-- THE SCRIPT --
DECLARE #SQL NVARCHAR(MAX) = '';
SELECT #SQL =
' SELECT Tab.Id, Tab.[Description], Tab2.*
FROM #ListOfTables AS Tab
CROSS JOIN ' + T.DetailTable + ' AS Tab2
WHERE Tab.Id = ' + CONVERT(VARCHAR(10),#Id)
FROM #ListOfTables T
WHERE T.Id = #Id;
PRINT #SQL
EXEC sp_executesql #SQL;
-- CLEAN UP --
DROP TABLE #ListOfTables;
DROP TABLE #bar;
DROP TABLE #foo;
However, I have to agree with the comments that this is a pretty nasty way to do things. If you want to choose particular columns and the columns are different for each detail table, then things will start to get really unpleasant... Does this give you something you can start with?
Remember, the best solution will almost certainly involve redesigning things so you don't have to jump through these hoops!
All of the detail tables must have identical schema.
Create a view that unions all the tables
CREATE VIEW vAllDetails AS
SELECT 'DETAIL1' table_name, * from DETAIL1
UNION ALL
SELECT 'DETAIL2' table_name, * from DETAIL2
UNION ALL
SELECT 'DETAIL3' table_name, * from DETAIL3
When you join against this view, SQL Server can generate a plan that uses a "startup predicate expression". For example, a plan like this: sample plan. At first glance, it looks like SQL is going to scan all of the detail tables, but it won't. The left most filters include a "startup predicate", so for each row we read from table1, only if TableName matches will that branch be executed.

Insert Into Selected Table name

I would like to do something like this in SQL Server:
INSERT INTO(Here I have SELECT which return Table name) (col1, col2, col3)
VALUES (a, b, c)
I build table name by using the Select statement and I would like to insert some values into this table.
Is it possible to do?
you can do with dynamic SQL
declare #table varchar(100),#sqlst varchar(max)
select #table=tablename from tables
set #sqlst ='insert into '+ #table +'(1,2,3) values(''a'',''b'',''c'')'
exec(#sqlst)
You can do this via a dynamic query like below
DECLARE #Q nvarchar(MAX)
SELECT #Q=N'INSERT INTO '+ tablename +N' (1,2,3) values(''a'',''b'',''c'')' FROM SomeTable
EXEC(#Q)
Please note that since alphanumeric values like a,b,c need to be inserted with single quotes, you'll have to escape the single quotes by another quote

SQL Query Delete rows from a table

I have a table #temp. The data in #temp are table names in a database. I wish to only show the table names of which the table has data. How can I do this without using dynamic SQL?
My sample data is as below:
create TABLE #temp (Table_Name VARCHAR(50))
insert into #temp values ('#temp1')
,('#temp2')
,('#temp3')
,('#temp4')
create TABLE #temp1 (Col1 int)
insert into #temp1 values (1)
,(3)
,(4)
create TABLE #temp2 (Col1 int)
insert into #temp2 values (7)
,(9)
,(6)
create TABLE #temp3 (Col1 int)
create TABLE #temp4 (Col1 int)
I manually delete the blank tables, How to do this using a query for numerous blank tables?
DELETE FROM #temp
WHERE Table_Name = '#temp3'
or Table_Name = '#temp4'
This is the result I want
select * from #temp
-- It only shows the two table names which are not blank
DROP TABLE #temp
DROP TABLE #temp1
DROP TABLE #temp2
DROP TABLE #temp3
DROP TABLE #temp4
This is my old query for this question:
DECLARE #TABLE_NAME VARCHAR(50), #COMMAND VARCHAR(500), #COUNT INT, #COUNTT INT
DECLARE #CountResults TABLE (CountReturned INT)
create TABLE #TABLE_NAME (TABLE_NAME VARCHAR(50))
SELECT #COUNTT= COUNT(*) FROM #temp
WHILE #COUNTT > 0
BEGIN
SELECT TOP 1 #TABLE_NAME = Table_Name FROM #temp
SET #COMMAND = 'SELECT COUNT(*) FROM ' + #TABLE_NAME
INSERT #CountResults EXEC (#COMMAND)
SET #Count = (SELECT * FROM #CountResults)
BEGIN TRANSACTION
DELETE #CountResults
ROLLBACK TRANSACTION
IF(#Count > 0)
BEGIN
INSERT INTO #TABLE_NAME VALUES (#TABLE_NAME)
END
DELETE FROM #temp WHERE Table_Name = #TABLE_NAME
SELECT #COUNTT= COUNT(*) FROM #temp
END
SELECT * FROM #TABLE_NAME
I don't know of any way to determine whether or not a table is empty without querying that table, which in your case means dynamic SQL. Your comments make it sound like you're okay with this but are looking for a way to do this more concisely than using a loop. Here's a (limited) possibility:
declare #sql nvarchar(max);
select #sql =
-- coalesce() ensures that UNION ALL is inserted before every SELECT but the first.
coalesce(#sql + N' union all ', N'') +
-- Select each table name. Note that SQL Server allows table names that contain
-- single quotes. In this case (or in the case of plain old bad/malicious data in
-- #temp), we need to make sure those characters are enclosed within the string
-- literal we're building.
N'select ''' + replace(table_name, N'''', N'''''') +
-- Use EXISTS to make sure there are one or more records in the table.
N''' where exists (select 1 from ' + quotename(table_name) + N')'
from #temp;
exec sp_executesql #sql;
This will build and execute a query that looks like this:
select '#temp1' where exists (select 1 from [#temp1])
union all
select '#temp2' where exists (select 1 from [#temp2])
union all
select '#temp3' where exists (select 1 from [#temp3])
union all
select '#temp4' where exists (select 1 from [#temp4])
This approach has a few limitations that you should be aware of:
The query will fail if #temp contains any string which is not the name of a table or view. Normally I'd suggest mitigating this by using object_id() or querying INFORMATION_SCHEMA.TABLES, but the fact that you've loaded #temp with the names of other temp tables complicates matters.
The query will also fail if #temp contains a table name that explicitly names the table schema, e.g. dbo.Stuff, because quotename() will render it as [dbo.Stuff] rather than [dbo].[Stuff]. But if you omit quotename(), you run the risk of incorrect and/or damaging behavior if a table_name contains spaces or other problematic characters.
In short, if you just want something for personal use and are okay with making certain assumptions about the data in #temp, then something like the above ought to work. But if you want something that will work correctly and safely under any circumstances, then it's going to take some doing, enough so that even if you could avoid using some kind of a loop, doing so is unlikely to make things any less complicated.
I have a method that does not use dynamic sql. It uses the sysindexes table, which according to Microsoft is subject to change at their whim. So this may not be a good candidate for a production system. But it could be a good place to start. This is also a bit easier if your source table is not a temp table, since temp tables have actual names that do not match the name used to create them.
This script worked for me on SQL Server 2008 r2.
-- drop table #MyTempTable;
Create table #MyTempTable(Table_Name varchar(50));
insert #MyTempTable values ('#MyTempTable2');
insert #MyTempTable values ('#MyTempTable3');
insert #MyTempTable values ('#MyTempTable4');
Create table #MyTempTable2 (Col1 int);
insert #MyTempTable2 values (1);
Create table #MyTempTable4 (Col1 int);
Create table #MyTempTable3 (Col1 int);
SELECT *
FROM #MyTempTable M1
JOIN tempdb.sys.tables T ON T.name LIKE (M1.Table_Name + '%')
JOIN [tempdb].[dbo].[sysindexes] S ON S.id = T.object_id
WHERE S.rowcnt > 0
It's not an ideal solution, but it satisfies your requirements. If you play around with it in your environment, it might give you some insight into a better way to achieve your larger goals. good luck.
EDIT: sysindexes will have one entry per index on the table. Or in the case of my example, for the heap (with no index.) So if your base tables have multiple indexes, you will need to modify the query a bit. Maybe change the JOIN and WHERE clause to a WHERE EXISTS SELECT * FROM [tempdb].[dbo].[sysindexes] S WHERE S.id = T.object_id AND S.rowcnt > 0 Play with it and you should be able to get where you were asking.
EDIT 2: Replacing sys.tables with sysobjects.
SELECT *
FROM #MyTempTable M1
JOIN [tempdb].[dbo].[sysobjects] O ON O.name LIKE (M1.Table_Name + '%')
JOIN [tempdb].[dbo].[sysindexes] S ON S.id = O.id
WHERE S.rowcnt > 0
Based on DeadZone's Query, the following works for non temp tables:
SELECT DISTINCT Table_Name
INTO #TABLE_NAME
FROM #Temp M1
JOIN [dbo].[sysobjects] O ON O.name LIKE (M1.Table_Name + '%')
JOIN [dbo].[sysindexes] S ON S.id = O.id
WHERE S.rowcnt > 0

Passing parameter to a SQL Server stored procedure

I am trying to write a SQL query and that works, but the stored procedure is not working when I try with parameters.
Example :
select *
from Table1
where Name = 'BEST People' // this works
// this does not show any rows
declare #Name nvarchar(128)
set #Name= 'BEST People'
select *
from Table1
where Name = #Name
Even when I try with a stored procedure, it does not work.
Depending on your column collation String Comparison Work
Specify Your Question Like This
Here's how you would check your column collation:
DECLARE #TableId INT
SELECT #TableId=id FROM sys.sysobjects
WHERE xtype='U' AND name='Table1'; --Your table name here
SELECT name, collation_name FROM sys.columns
WHERE object_id=#TableId AND name=N'Name'; --Your column name here
View Collation Information
You need to cast the string to NVARCHAR:
declare #Name nvarchar(128)
set #Name= N'BEST People'
select * from Table1 where Name = #Name
Without the N it will be a VARCHAR

Resources