What does something like
SELECT 'DROP INDEX' || 'some other string'
mean?
I know usually you have the column name after the select, like SELECT first_name, but what does it mean when it is in single quotes? I believe the || means to concatenate the strings. Sorry, I'm new to this and couldn't seem to find anything about this.
EDIT: Sorry I realized my question was not very clear. I meant to ask what does it mean if the SELECT was followed by a SQL command in single quotes? Would it be any different? Would it also just create a column with DROP INDEX as the header? Something like
SELECT 'DROP INDEX' || 'some other string'
FROM ...
WHERE...
The idea here is to generate SQL statements from database metadata so that you can later execute them as a script. That is a two-step process: first you run an SQL statement that generates SQL statements, then you execute those SQL statements (unless you are using psql, where \gexec can do that in a single step).
But if you use the string concatenation operator || to construct the statements, you run the risk of SQL injection.
For example, to delete all tables in a schema, you could generate a script with
SELECT 'DROP TABLE ' || table_schema || '.' || table_name
FROM information_schema.tables
WHERE table_schema = 'my_schema';
Now if there happens to be a table called My-Table, that script would fail, since that is not a standard conforming SQL identifier and would have to be quoted.
And that is also not safe:
SELECT 'DROP TABLE "' || table_schema || '"."' || table_name || '"'
FROM information_schema.tables
WHERE table_schema = 'my_schema';
because there could be a table called silly"name.
By crafting tables with names like existing_table"; DROP TABLE "important, you could abuse such a statement to create havoc in the database.
Avoid string concatenation and use format:
SELECT format('DROP TABLE %I.%I', table_schema, table_name)
FROM information_schema.tables
WHERE table_schema = 'my_schema';
Selecting a string will return the string value.
SELECT 'string here'
Will return string here
|| is short hand for concatenation.
SELECT 'string' || ' here'
Will return string here.
EDIT:
Selecting a SQL command will return the SQL command in the message. This is often done when creating dynamic SQL and wanting to validate the SQL command before executing it. If you put a SQL command in the #sql NVARCHAR(max) variable, you can SELECT #sql to return the query or EXEC sp_executesql #sql to execute the SQL command (SQL Server syntax).
SELECT name, 'is a human' AS Note FROM people
The result would be a table with 2 colums: Name and Note.
Name would be the person's name and Note would always say 'is a human'.
|| is the logical OR operator.
Links:
http://www.geeksengine.com/database/basic-select/literal-character-strings.php
http://www.geeksengine.com/database/basic-select/using-logical-operators.php
Edit:
It was not the question but DROP INDEX is a SQL command: https://www.w3schools.com/SQL/sql_ref_drop_index.asp
Related
i want to use the result of a query as an input in another query.
What might make it difficult: The variable is the schema in the database.
CREATE or replace VARIABLE myschema varchar(15) ;
set myschema = (select owner from syscat.tables where tabname = 'xyz');
select count(name) as result from myschema.USR02 where USTYP = 'A';
DROP VARIABLE myschema;
This is my last try, after i failed using declare.
But i get an error, because "myschema" is used as a string, and of course there is no schema with name "myschema". The result of the first query is not used.
If I just run the first two lines, i get the schemaname as result. Do i have to mark the variable in a special way? The goal is just the result of the query in line 3 by using the dynamic value of "myschema".
Unfortunately, you have to use dynamic SQL (forming a custom SQL query through string manipulation) if you want to deal with table, schema, or column names dynamically:
This is the basic idea:
execute immediate 'select * from ' || myschema || '.USR02';
However, you can't just run a bare select in dynamic SQL; you have to put the result in something. And the whole thing must be in a compound SQL block. So the full example would look something like this (simplified query for space).
This query assumes that a table called "result" exists to store the result you are returning.
begin
declare myschema varchar(100) default '';
set myschema = (select owner from syscat.tables where tabname = 'xyz');
execute immediate 'insert into result select count(*) from ' || myschema || '.USR02';
end
select * from result;
Note that within the block, you can simply declare a variable (as shown in my example). So you don't have to declare a global variable for this purpose, unless you want it to persist beyond this one statement.
I renamed a table and since, in evry 'select' I get the 'Invalid object name' for all columns.
I get from my select the output I need, but why I get an error too ?
this is my simple select...
SELECT [Importance]
,[Color]
,[NotificationName]
FROM [dbo].[Alerts]
It looks like you're using SQL Server Management Studio. I suspect your query will run if you try it, it's just that the intellisense doesn't know that the table name has changed.
Try Ctrl+Shift+R to refresh the cache or alternatively Edit -> Intellisense -> Refresh Local Cache.
You need to do this every time you perform schema changes.
Run below query to confirm that your table has been renamed and has the exact column names specified in your select query:
select * from sys.all_columns where object_id = OBJECT_ID('Alerts')
Alternatively you can execute below query to confirm that the Alerts table exists
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'Alerts'))
BEGIN
PRINT 'Alerts exists'
END
Also make sure you are in the correct database, run below query to find out the database to which Alerts belong :
SELECT TABLE_CATALOG
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'Alerts'
Once you got the database name add USE DATABASENAME at the beginning of your query or you can use DATABASENAME.dbo.Alerts.
I have a CTE in which a SELECT statement is generated, but SQL Server (2012) does not allow calling EXEC on it. Here's the query:
DECLARE #guidToFind uniqueidentifier = 'E4069560-091A-4026-B519-104F1C7693B3';
WITH GuidCols (TableName, ColName, Query) As
(
SELECT
C.TABLE_NAME,
C.COLUMN_NAME,
'SELECT ' +
QUOTENAME(C.TABLE_NAME) + '.' +
QUOTENAME(C.COLUMN_NAME) + '
FROM ' +
QUOTENAME(C.TABLE_NAME) + '
WHERE ' +
QUOTENAME(C.COLUMN_NAME) + ' = ''' + cast(#guidToFind AS VARCHAR(50))+
''''
FROM
INFORMATION_SCHEMA.COLUMNS C
INNER JOIN INFORMATION_SCHEMA.TABLES T
ON C.TABLE_NAME = T.TABLE_NAME AND
T.TABLE_TYPE = 'BASE TABLE'
WHERE
C.DATA_TYPE = 'uniqueidentifier'
)
-- SELECT * FROM
EXEC( GuidCols.Query )
The problem is not solve if I uncomment the SELECT statement after CTE.
The purpose of this query is to find all instances of a GUID in a database. Currently I'm solving this problem using a script like this. However I would be happier to solve this problem without iterating through rows, using set operations and other techniques.
You can not use exec as a part of a CTE.
From WITH common_table_expression (Transact-SQL)
A CTE must be followed by a single SELECT, INSERT, UPDATE, or DELETE
statement that references some or all the CTE columns.
What you can do instead is to store the result from your query in a temp table, loop over the rows and execute one statement at a time.
The EXEC() function is available from T-SQL, but it is not accessible from within a SQL statement. I would assume this is the case because SQL is executed in several steps... something like:
Your statement is parsed.
An execution plan is generated.
The execution plan is run against the database and results are returned.
The EXEC() function is designed to dynamically execute a statement, so in order to do what you're asking, SQL Server would have to perform the first two steps, then while executing the statement, it would have to return back to the first step to parse/execute the dynamic statement. This would have to be repeated for each row in your results.
I assume this type of 'feature' is not available because it could adversely affect the performance and complexity of the db engine; so they leave it to us to execute the first statement, then loop through each record to execute the dynamic statements individually.
Exec executes a T-SQL command that you embed in its parentheses. The difference is that the EXEC() function can execute a string or string variable, as you saw in the preceiding code. The argument for EXEC() can be a literal string, but the real power of EXEC() comes to light when you use a variable.
It executes the command contained in the variable, but in a different context from the session calling the function. That's important, because it introduces some severe constraints. Any tables you create are visible to the EXEC() context, but variables declared by the calling session aren't visible to the EXEC() context, and vice versa.
I found an interesting article related to this at : http://msdn.microsoft.com/en-us/library/aa175921(v=sql.80).aspx
Although above is self sufficient, you can also go through : http://blog.sqlauthority.com/2007/09/13/sql-server-difference-between-exec-and-execute-vs-exec-use-execexecute-for-sp-always/
You may use OPENQUERY instead of EXEC:
SELECT * FROM OPENQUERY (OracleSvr, 'SELECT name FROM joe.titles WHERE name = ''NewTitle''');
Reference: https://learn.microsoft.com/en-us/sql/t-sql/functions/openquery-transact-sql?view=sql-server-2017
So i'm a pretty good systems admin and can manage mysql servers with no issue. My problem is in actually coding sql, and more specifically coding sql I feel safe to automate in nightly scripts. Thats where you awesome stack overflow guys come in.
I currently have my production wordpress site sync to my dev server so we have as close to live for testing on before a push to production. Right after I update the mysql to be a copy of production I need to find and replace about 2,000 strings.
All I need to do is find a way to execute SQL to find and replace http://DrunkOnJudgement.com to http://dev.DrunkOnJudgement.com any place in any table.
Help me Obi wan Kenobis your my only hope.
You want to do something like this
update table_name
set column_name = replace(column_name, 'http://dev.DrunkOnJudgement.com', 'http://DrunkOnJudgement.com');
this will ensure that you simply replace the text you are looking for in a specific column with the text you want it to be without changing any text around it.
so for example you could just shorten it to something like: replace(column_name, 'dev.DrunkOnJudgment.com', 'DrunkOnJudgment.com')
You can also specify a where clause so that you only replace items that contain that text so something like this:
where column_name like '%dev.DrunkOnJudgement.com%'
Ok to do something like this for all columns in all tables, basically search the entire db. You can use a statement like this:
SELECT Concat('UPDATE ', TABLE_NAME, ' SET ', COLUMN_NAME, ' = REPLACE(', COLUMN_NAME, ',''dev.DrunkOnJudgment.com'',''DrunkOnJudgment.com'')', ' WHERE ', COLUMN_NAME, ' like ''%dev.DrunkOnJudgment.com%''' ) FROM INFORMATION_SCHEMA.COLUMNS
it will output a sql statement like the one above for each column and table in the database and because you are using a replace statement if it does not find the text it does not replace anything it also ensure you only update records that actually contain that text.
So to automate this you would use a cursor, I have not tested the following code but it would look something like this:
DECLARE done BOOLEAN DEFAULT 0;
DECLARE sql VARCHAR(2000);
DECLARE cmds CURSOR
FOR
SELECT Concat('UPDATE ', TABLE_NAME, ' SET ', COLUMN_NAME, ' = REPLACE(', COLUMN_NAME, ',''dev.DrunkOnJudgment.com'',''DrunkOnJudgment.com'')', ' WHERE ', COLUMN_NAME, ' like ''%dev.DrunkOnJudgment.com%''' ) FROM INFORMATION_SCHEMA.COLUMN;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
OPEN cmds;
REPEAT
FETCH cmds INTO sql;
PREPARE stmt FROM sql;
EXECUTE stmt;
DROP PREPARE stmt;
UNTIL done END REPEAT;
CLOSE cmds;
Is this as simple as an update statement with a where clause?
update myTable
set myCol = 'http://dev.DrunkOnJudgement.com'
where myCol = 'http://DrunkOnJudgement.com'
At this point in your product's life cycle I guess it is too late to suggest working out a solution that takes away this issue entirely?
For example, not using absolute URLs, or replacing the urls with some variable that is evaluated at runtime?
I am working on application which can deal with multiple database servers like "MySQL" and "MS SQL Server".
I want to get tables' names of a particular database using a general query which should suitable for all database types. I have tried following:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
But it is giving table names of all databases of a particular server but I want to get tables names of selected database only. How can I restrict this query to get tables of a particular database?
Probably due to the way different sql dbms deal with schemas.
Try the following
For SQL Server:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='dbName'
For MySQL:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA='dbName'
For Oracle I think the equivalent would be to use DBA_TABLES.
Stolen from here:
USE YOURDBNAME
GO
SELECT *
FROM sys.Tables
GO
The following query will select all of the Tables in the database named DBName:
USE DBName
GO
SELECT *
FROM sys.Tables
GO
Just put the DATABASE NAME in front of INFORMATION_SCHEMA.TABLES:
select table_name from YOUR_DATABASE.INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
USE DBName;
SELECT * FROM sys.Tables;
We can deal without GO in-place of you can use semicolon ;.
In mysql, use:
SHOW TABLES;
After selecting the DB with:
USE db_name
In order if someone would like to list all tables within specific database without using the "use" keyword:
SELECT TABLE_NAME FROM databasename.INFORMATION_SCHEMA.TABLES
This works Fine
SELECT
*
FROM
information_schema.tables;
I did not see this answer but hey this is what I do :
SELECT name FROM databaseName.sys.Tables;
To select the database query below :
use DatabaseName
Now
SELECT * FROM INFORMATION_SCHEMA.TABLES
Now you can see the created tables below in console .
PFA.
For Mysql you can do simple. SHOW TABLES;
select * from sys.tables
order by schema_id --comments: order by 'schema_id' to get the 'tables' in 'object explorer order'
go
In our Oracle DB (PL/SQL) below code working to get the list of all exists tables in our DB.
select * from tab;
and
select table_name from tabs;
both are working. let's try and find yours.
SELECT TABLE_NAME
FROM your_database_name.INFORMATION_SCHEMA.TABLES
ORDER BY TABLE_NAME;
Exec sp_MSforeachtable 'Select ''?'''
USE dbName;
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_SCHEMA = 'dbName' OR TABLE_SCHEMA = 'schemaName')
ORDER BY TABLE_NAME
If you are working with multiple schemata on an MS SQL server, then SELECT-ing TABLE_NAME without also simultaneously selecting TABLE_SCHEMA might be of limited benefit, so I have assumed we are interested in the tables belonging to a known schema when using MS SQL Server.
I have tested the query above with SQL Server Management Studio using an SQL Server database of mine and with MySQL Workbench using a MySQL database, and in both cases it gives the table names.
The query bodges Michael Baylon's two different queries into one that can then run on either database type. The first part of the WHERE clause works on MySQL databases and the second part (after the OR) works on MS SQL Server databases. It is ugly and logically a little incorrect as it supposes that there is no undesired schema with the same name as the database. This might help someone who is looking for one single query that can run on either database server.
UPDATE FOR THE LATEST VERSION OF MSSQL SERVER (17.7)
SELECT name FROM sys.Tables WHERE type_desc = 'USER_TABLE'
Or SELECT * for get all columns.
Yes oracle is :
select * from user_tables
That is if you only want objects owned by the logged in user/schema otherwise you can use all_tables or dba_tables which includes system tables.
Building from Michael Baylon's answer, I needed a list which also included schema information and this is how I modified his query.
SELECT TABLE_SCHEMA + '.' + TABLE_NAME as 'Schema.Table'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG = 'dbName'
ORDER BY TABLE_SCHEMA, TABLE_NAME
Simply get all improtanat information with this below SQL in Mysql
SELECT t.TABLE_NAME , t.ENGINE , t.TABLE_ROWS ,t.AVG_ROW_LENGTH,
t.INDEX_LENGTH FROM
INFORMATION_SCHEMA.TABLES as t where t.TABLE_SCHEMA = 'YOURTABLENAMEHERE'
order by t.TABLE_NAME ASC limit 10000;
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME
for postgres it will be:
SELECT table_name
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'your_schema' -- probably public