am I using </table> wrong? - html

`I am creating an automatic mail using de msdb function but when the sql is converted to HTML and send in outlook the table data rows keep adding and outlook crashes.
while only one row is expected, as shows when I just run the query.
This is what I have at this moment
DECLARE #tableHTML NVARCHAR(max) = '';
SET #tableHTML =
'<h1>Picking en Rework</h1>' +
'<table border="1">' +
'<tr>' +
'<th>Order ETA</th>' +
'<th>To be Picked</th>' +
'<th>Rework Actions</th>' +
'<th>Destination Plts req order-line</th>' +
'<th>Destination Plts Req Total</th>' +
'<th>Reworked Plts On Stock</th>' +
'<th>Plts Left To Rework Order-Line</th>' +
'<th>Plts Left To Rework total</th>' +
'</tr>' +
CAST
(
(
SELECT
td = coalesce(vOuttakeOrderHeaders_2057.[ETA], ''), '',
td = coalesce([To be Picked], ''), '',
td = coalesce(vReworkReq_2057.[Rework Actions], ''), '',
td = coalesce(vReworkReq_2057.[Destination Plts Req Order-Line],
''),'',
td = coalesce(vReworkReq_2057.[Destination Plts Req total], ''), '',
td = coalesce(vReworkReq_2057.[Reworked Plts On Stock], ''), '',
td = coalesce(vReworkReq_2057.[Plts Left To Rework Order-Line], ''),
'',
td = coalesce(vReworkReq_2057.[Plts Left To Rework total], ''), ''
FROM [dbo].[vMailReworkPicking_2057], vOuttakeOrderDetails_2057
left join vOuttakeOrderHeaders_2057 on
vOuttakeOrderDetails_2057.iOrderHeaderSysID =
vOuttakeOrderHeaders_2057.iOrderHeaderSysID
left join vReworkReq_2057 on vOuttakeOrderDetails_2057.Article =
vReworkReq_2057.Article
left join vMailReworkPicking_2057 on vOuttakeOrderHeaders_2057.[ETA] =
vMailReworkPicking_2057.[Order ETA]
Where
vOuttakeOrderHeaders_2057.[Order Type] like 'outtake'
and DisposedQuantity < TargetQuantity
and RestPick > 0
ORDER BY vOuttakeOrderHeaders_2057.[ETA] DESC
FOR XML PATH('tr'), type) as nvarchar(max)) +
'</table>';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'test123',
#recipients = 'email',
#subject = 'Picking & Rework',
#body = #tableHTML,
#body_format = 'HTML';`

Related

SSRS Download All History Snapshots

Is it possible to download all the history snapshots of a report at once? Preferably as a CSV. Would save a lot time instead of clicking into each one individually and selecting save as CSV.
I only see the option to Delete
In PowerShell, you can loop through each snapshot and save them using this example:
<#
Description: Save SSRS Report Snapshots
#>
$sql = "
DECLARE #ReportName NVARCHAR(200) = 'Your Report Name'; --change to NULL for every snapshot
DECLARE #FileFormat NVARCHAR(50) = 'CSV'; --HTML5,PPTX,ATOM,HTML4.0,MHTML,IMAGE,EXCEL (for .xls),EXCELOPENXML (for .xlsx),WORD (for .doc),WORDOPENXML (for .docx),CSV,PDF,XML
DECLARE #FileExtn NVARCHAR(50) = 'csv';
DECLARE #ServerName NVARCHAR(100) = 'http://YourServerName';
DECLARE #DateFrom DATE = CAST(DATEADD(DAY, -1, GETDATE()) AS DATE); --change to NULL for every snapshot
DECLARE #ExportPath NVARCHAR(200) = 'C:\Temp\';
SELECT
--[ReportID] = [c].[itemid]
-- , [ReportName] = [c].[name]
-- , [ReportPath] = [c].[path]
-- , [SnaphsotDate] = FORMAT([h].[snapshotdate], 'dd-MMM-yyyy')
-- , [SnapshotDescription] = [s].[DESCRIPTION]
-- , [SnapshotEffectiveParams] = [s].[effectiveparams]
-- , [SnapshotQueryParams] = [s].[queryparams]
-- , [ScheduleName] = [sc].[name]
-- , [ScheduleNextRunTime] = CONVERT(VARCHAR(20), [sc].[nextruntime], 113)
[ExportFileName] = #ExportPath + REPLACE([c].[name], ' ', '_') + '_' + FORMAT([h].[snapshotdate], 'yyyyMMdd_HHmm') + '.' + #FileExtn
, [SnapshotUrl] =
#ServerName
+ '/ReportServer/Pages/ReportViewer.aspx?'
+ [c].[path] + '&rs:Command=Render&rs:Format='
+ #FileFormat + '&rs:Snapshot='
+ FORMAT([h].[snapshotdate], 'yyyy-MM-ddTHH:mm:ss')
FROM
[ReportServer].[dbo].[History] AS [h] WITH(NOLOCK)
INNER JOIN [ReportServer].[dbo].[SnapshotData] AS [s] WITH(NOLOCK) ON [h].[snapshotdataid] = [s].[snapshotdataid]
INNER JOIN [ReportServer].[dbo].[Catalog] AS [c] WITH(NOLOCK) ON [c].[itemid] = [h].[reportid]
INNER JOIN [ReportServer].[dbo].[ReportSchedule] AS [rs] WITH(NOLOCK) ON [rs].[reportid] = [h].[reportid]
INNER JOIN [ReportServer].[dbo].[Schedule] AS [sc] WITH(NOLOCK) ON [sc].[scheduleid] = [rs].[scheduleid]
WHERE
1=1
AND [rs].[reportaction] = 2
AND (#ReportName IS NULL OR [c].[Name] = #ReportName)
AND (#DateFrom IS NULL OR [h].[snapshotdate] >= CAST(DATEADD(DAY, -1, GETDATE()) AS DATE))
ORDER BY
[c].[name]
, [h].[snapshotdate];
;"
$server = 'YourServerName';
$dbs = 'MASTER';
$dsn = "Data Source=$server; Initial Catalog=$dbs; Integrated Security=SSPI;";
$cn = New-Object System.Data.SqlClient.SqlConnection($dsn);
#execute merge statement here with parameters
$cn = New-Object System.Data.SqlClient.SqlConnection($dsn);
$cn.Open();
$cmd = $cn.CreateCommand();
$cmd.CommandText = $sql
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $cmd
$cmd.Connection = $cn
$ds = New-Object System.Data.DataSet
$SqlAdapter.Fill($ds)
$cn.Close()
$Result = $ds.Tables[0]
Foreach ($item in $Result)
{
#Write-Host $item.name
$SnapshotUrl = $item.SnapshotUrl
$ExportFileName = $item.ExportFileName
(Invoke-WebRequest -Uri $SnapshotUrl -OutFile $ExportFileName -UseDefaultCredentials -TimeoutSec 240);
}
https://learn.microsoft.com/en-us/sql/reporting-services/url-access-parameter-reference?view=sql-server-ver15
Was having trouble with powershell, so thought I'd post simplified version of my rough Python solution inspired by the resource from #aduguid's answer.
import requests
from requests_negotiate_sspi import HttpNegotiateAuth
import os
def downloadFile(url, file_name, download_folder, session):
response = session.get(url, stream=True) # open the download link
file_path = os.path.join(download_folder, file_name)
with open(file_path, 'wb') as file: # create a new file with write binary mode
for chunk in response.iter_content(chunk_size=1024):
if chunk:
file.write(chunk)
# Can also use '/Reports()' for non-linked reports.
# Can also pass in 'path="<report_path>"' instead of using id numbers,
# e.g. '.../Reports(path="/cool%20reports/my%20report")/HistorySnapshots'
api_url = r'http://<server_name>/reports/api/v2.0/LinkedReports(<item_id>)/HistorySnapshots'
session = requests.session()
session.auth = HttpNegotiateAuth() # uses windows log in
response = session.get(api_url)
hs_snapshot_list = response.json()['value']
for item_dict in hs_snapshot_list:
download_url = (r'http://<server_name>/ReportServer/Pages/ReportViewer.aspx?<report_path>'
+ '&rs:Snapshot=' + item_dict['HistoryId']
+ '&rs:Format=CSV')
downloadFile(download_url, '<your_file_name>', '<your_download_folder>', session)
SSRS API Resource:
https://app.swaggerhub.com/apis/microsoft-rs/SSRS/2.0#/Reports/GetReportHistorySnapshots

SQL Server Agent job history to HTML report

I am trying to output SQL Server Agent job history into an HTML report and send it to mail as a check in office.
Here's my code:
$tabName = "Report"
$table = New-Object system.Data.DataTable "$tabName"
$col1 = New-Object system.Data.DataColumn "Server",([string])
$col2 = New-Object system.Data.DataColumn "Job Name",([string])
$col3 = New-Object system.Data.DataColumn "Step Name",([string])
$col4 = New-Object system.Data.DataColumn "Message",([string])
$col5 = New-Object system.Data.DataColumn "RunDate",([string])
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
$table.columns.add($col4)
$table.columns.add($col5)
$data = (Get-SqlAgentJobHistory -ServerInstance SQLServ1 -JobName "syspolicy_purge_history" -Since Yesterday | Select-Object Server, JobName, StepName, Message, RunDate )
$row = $table.NewRow()
$row."Server" = ($data."Server")
$row."Job Name" = ($data."JobName")
$row."Step Name" = ($data."StepName")
$row."Message" = ($data."Message")
$row."RunDate" = ($data."RunDate")
$table.Rows.Add($row)
$Head = #"
<style>
body {
font-family: "Arial";
font-size: 8pt;
color: #4C607B;
}
th, td {
border: 1px solid #e57300;
border-collapse: collapse;
padding: 5px;
}
th {
font-size: 1.2em;
text-align: left;
background-color: #003366;
color: #ffffff;
}
td {
color: #000000;
}
.even { background-color: #ffffff; }
.odd { background-color: #bfbfbf; }
</style>
"#
$Report = [string]$body = [PSCustomObject]$table | select-Object Server, JobName, StepName, Message, RunDate | ConvertTo-HTML -head $Head -Body "<font color=`"Black`"><h4>SQL Job History</h4></font>" | Out-File "C:\Users\Administrator\Documents\scripts\sql job history\report.html"
The HTML fields I've added display when I output the report but not the content.
Any advise on this one please?
You need to foreach over the results from Get-SqlAgentJobHistory, eg
foreach ( $r in $data )
{
$row = $table.NewRow()
$row."Server" = ($r."Server")
$row."Job Name" = ($r."JobName")
$row."Step Name" = ($r."StepName")
$row."Message" = ($r."Message")
$row."RunDate" = ($r."RunDate")
$table.Rows.Add($row)
}
Try the code below. It sends an email with jobs information for the last 24 hours.
Just replace 'email_recipients_list' and 'url_to_ssis_jobs_monitoring_report' with relevant values.
DECLARE
#email_recipients VARCHAR(128)
, #email_subject NVARCHAR(128)
, #email_body_format VARCHAR(128)
, #email_body NVARCHAR(MAX)
, #job_count INT
, #table_style VARCHAR(512)
, #from datetime
, #periode NVARCHAR(512)
, #url_to_ssis_jobs_monitoring_report VARCHAR(128)
SET #email_recipients='email_recipients_list'
SET #email_body_format='HTML'
SET #table_style = 'cellpadding="2" cellspacing="2" border="1" style="border-collapse: collapse; border: 1px solid black;"';
SET #from = DATEADD(day, -1, getdate())
SET #periode = 'between ' + FORMAT(DATEADD(d, -1, GETDATE()), 'yyyy-MM-dd HH:MM:ss') + ' and ' + FORMAT(GETDATE(), 'yyyy-MM-dd HH:MM:ss')
SET #email_subject = 'SSIS Jobs ' + #periode
SET #url_to_ssis_jobs_monitoring_report = 'url_to_ssis_jobs_monitoring_report'
DECLARE #job_table NVARCHAR(MAX)
DECLARE #job TABLE(
[Start time] NVARCHAR(19)
, [Job] NVARCHAR(128)
, [Job execution status] NVARCHAR(128)
, [Execution time] NVARCHAR(8)
);
WITH subset As (
SELECT
CAST(left(t1.run_date,8) As DATETIME) + CAST(STUFF(STUFF(RIGHT('000000'+ISNULL(CAST(t1.run_time As NVARCHAR(6)),''),6),5,0,':'),3,0,':') As datetime) As [Start time]
, t1.job_id As 'Id Job'
, t1.name As Job
, CASE IIF(MIN(t2.run_status) = 1, MAX(t2.run_status), MIN(t2.run_status))
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Canceled'
WHEN 4 THEN 'In Progress'
ELSE 'Unknown'
END As [Status]
, CONVERT(TIME(0), DATEADD(SECOND,
SUM(
DATEDIFF(SECOND,0,CAST(CAST(STUFF(STUFF(RIGHT('000000'+ISNULL(CAST(t2.run_duration As NVARCHAR(6)),''),6),5,0,':'),3,0,':') As TIME) As DATETIME))
)
, 0)
) As 'Execution time'
FROM (
SELECT
sjh.job_id
,sj.name As name
,sjh.run_date
,sjh.run_time
,LEAD(sjh.run_time,1) OVER ( ORDER BY run_date, run_time) As next_run_time
,MIN(sjh.run_status) As run_status
FROM [msdb].[dbo].[sysjobhistory] sjh
LEFT JOIN [msdb].[dbo].[sysjobs] sj
ON sjh.job_id = sj.job_id
WHERE
sjh.step_id = 1
-- To exclude unrelevant jobs
AND TRY_CONVERT(UNIQUEIDENTIFIER,sj.name) IS NULL
GROUP BY sjh.job_id, sj.name, sjh.run_date, sjh.run_time
) t1
LEFT JOIN [msdb].[dbo].[sysjobhistory] t2
ON
t2.job_id = t1.job_id
AND t2.run_date = t1.run_date
WHERE
t2.job_id = t1.job_id
AND t2.run_date = t1.run_date
AND t2.step_id <> 0
AND CAST(left(t1.run_date,8) As datetime) + CAST(STUFF(STUFF(RIGHT('000000'+ISNULL(CAST(t1.run_time As NVARCHAR(6)),''),6),5,0,':'),3,0,':') As datetime) > #from
-- To exclude unrelevant jobs
AND TRY_CONVERT(UNIQUEIDENTIFIER,t1.name) IS NULL
GROUP BY t1.job_id, t1.run_date, t1.run_time, t1.name, t1.next_run_time
)
INSERT INTO #job
SELECT
FORMAT(s.[Start time], 'yyyy-MM-dd HH:MM:ss') As [Start time]
, s.Job
, s.Status
, CAST(s.[Execution time] As NVARCHAR(8)) As [Execution time]
FROM subset s
SET #job_count = ##ROWCOUNT
If #job_count > 0
BEGIN
SET #job_table = CAST( (
SELECT td = [Start time] + '</td><td>' + [Job] + '</td><td>' + [Job execution status] + '</td><td>' + [Execution time]
FROM (
SELECT *
FROM #job
) As d
ORDER BY [Start time]
FOR XML PATH( 'tr' ), TYPE ) As NVARCHAR(MAX) )
set #job_table = '<table ' + #table_style + '>'
+ '<tr><th>Start time</th><th>Job</th><th>Job execution status</th><th>Execution time</th></tr>'
+ replace( replace( #job_table, '<', '<' ), '>', '>' )
+ '</table>'
SET #email_body = #job_table
END
SET #email_body = '<h1>SSIS Jobs ' + #periode + '</h1>' + #email_body
SET #email_body = #email_body + '<br><br>SSIS jobs monitoring report'
-- Send email
EXEC msdb.dbo.sp_send_dbmail
#recipients=#email_recipients
, #body=#email_body
, #subject=#email_subject
, #body_format=#email_body_format

Tweepy information into MySQL - text being cut off

I am inserting information from twitter using Tweepy into a MySQL table. Mostly it works are intended however, the actual text from the tweet is being cut off and many end with "..." and I am not sure why this is.
An example of the output is this:
#JamesMelville: Remain voters are not "unpatriotic" by "talking the country down".Its the opposite. Remainers care about Britains fut…
Thanks for your help
Here is my stream listener class: (I am new to python so this is probably poor)
class listener(StreamListener):
def on_data(self, data):
try:
jsonData=json.loads(data)
tweets =(jsonData['text'])
if tweets.startswith('RT'):
retweets = True
else:
retweets = False
tweets = tweets.replace('RT', '')
tweets = tweets.replace("'", '')
tweets = tweets.lstrip()
tweets = tweets.replace('\n', '')
screen_name =(jsonData['user']['screen_name'])
name =(jsonData['user']['name'])
name = name.replace(',', ' ')
language =(jsonData['lang'])
location =(jsonData['place'])
coord =(jsonData['coordinates'])
device = jsonData['source'].split('">')[1].replace('</a>', '')
tweettime = jsonData['created_at'].replace('+', '')
tweettime = datetime.datetime.strptime(tweettime, "%a %b %d %H:%M:%S %f %Y")
date_to_string = str(tweettime.strftime("%Y/%m/%d,%H:%M:%S"))
date_created = date_to_string.split(',')[0]
time_created = date_to_string.split(',')[1]
created_time =(time_created)
created_date =(date_created)
htext = jsonData['entities']['hashtags']
htext2 = []
hashtag_list = ''
for hashtag in htext:
htext=str(hashtag['text'])
hashtag_list = hashtag_list + ' ::' + htext
hashtag_list = hashtag_list.replace("'", "")
conn = connect( host = '', port = , user = ', passwd = '', charset='utf8', autocommit = True);
conn.commit()
cursor = conn.cursor( cursors.DictCursor );
cursor.execute("CREATE DATABASE IF NOT EXISTS twitter")
cursor.execute("USE twitter")
cursor.execute( """CREATE TABLE IF NOT EXISTS `twitter_data`(ID INT AUTO_INCREMENT NOT NULL,`Name` VARCHAR( 200 ) ,`Screen name` VARCHAR( 200 ) , `Date created` VARCHAR ( 20 ), `Time created` VARCHAR ( 8 ), Tweet VARCHAR ( 200 ), Hashtags VARCHAR ( 200 ), Retweets VARCHAR ( 5 ), Lanugage VARCHAR ( 20 ), Device VARCHAR ( 60 ), Location VARCHAR( 200 ), Coordinates VARCHAR ( 200 ), PRIMARY KEY ( ID ))""" )
sql = "INSERT INTO `twitter_data` VALUES( Null, '" + str(name) + "', '" + str(screen_name) + "', '" + str(created_date) + "', '" + str(created_time) + "', '" + str(tweets) + "', '" + str(hashtag_list) + "', '" + str(retweets) + "', '" + str(language) + "', '" + str(device) + "', '" + str(location) + "', '" + str(coord) + "') "
print(sql)
cursor.execute(sql)
return True
except Exception as N:
print('failed on_data '+ str(N))
time.sleep(5)
I have found a solution to my question.
The text was being truncated when it was a retweet due to the 140 character limit.
Therefore it from nothing to do with MySQL.
My solution was to use the 'retweet_status' attribute (and split out the actual tweet text part) rather than 'text' if the tweet was a retweet, otherwise I just used 'text'.
Here is some of the code that was changed:
if tweets.startswith('RT'):
retweets = True
tweets = str(jsonData['retweeted_status']).split('\'text\':')[1]
if 'display_text_range' in tweets:
tweets = tweets.split(', \'display_text_range\'')[0]
else:
tweets = tweets.split(', \'source\'')[0]
else:
retweets = False
tweets = tweets.replace('RT', '')

loop to generate a unique url-frinedly route

I have a table in mariadb in this structure,
CREATE TABLE `items` (
`id` char(36), `route` varchar(255), `value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `route` (`route`)
)
I use the route column to get user-friendy urls, such as http://www.examle.com/this-is-the-route-of-an-item
When a user creates a new item, apart from omitting spaces and illegal characters, I would like to "catch" cases where the route chosen for the new item is in use, and generate a valid route.
For example, if route-of-an-item is already in use, i would fallback to route-of-an-item-a, or route-of-an-item-b, etc.
The naive solution could be querying db in a loop, for example (kind of pseudo code):
var additionalChars = "";
while (db.query("select count * from `items` where `route`='" + route + "-" + additionalChars + "'"))
additionalChars = nextAdditionalChars(additionalChars);
finalRoute = route + '-' + additionalChars;
Since this involves querying the db many times I thought of another solution.
var additionalChars = "";
var usedRoutes = db.query("select `route` from `items` where `route` like '" + route + "%'");
while(usedRoutes.contains(route + '-' + additionalChars))
additionalChars = nextAdditionalChars(additionalChars);
finalRoute = route + '-' + additionalChars;
Is there any better way to approach this kind of a problem?
Am I correct that the second solution would perform better?
If I use the second solution, should I add a fulltext index to route field?
You could sort your query by route descending and only retrieve and check one item. In your pseudo code this would look like:
var additionalChars = "";
var usedRoutes = db.query("select `route` from `items` where `route` like '" + route + "%' order by `route` desc limit 1");
if(usedRoutes.route is already in use)
additionalChars = nextAdditionalChars(additionalChars);
finalRoute = route + '-' + additionalChars;
Ok, so after consulting with a colleague I ended up using solution 2, here is the code (node.js), in case anyone faces this problem:
db access
var route = req.body.route || 'noname';
route = route.replace(/[\s_]/g, '-').toLowerCase().replace(/[^0-9a-z\u0591-\u05F4\u0621-\u064A\-_\s]/g, "").replace(/_+/g, ' ').trim().replace(/[\s_]+/g, '-');
var isArabic = (/[\u0621-\u064A]/g).test(route),
isHebrew = (/[\u0591-\u05F4]/g).test(route),
lang = isArabic ? 'ar' : (isHebrew ? 'he' : 'en');
Items.findAll({ where: { route: { $like: route + '%' } }, attributes: ['route'] })
.then((items) => {
var routes = _.keyBy(items, 'route'),
prefix = '';
while (routes[route + (prefix ? '-' + prefix : '')])
prefix = charactersCount(prefix, lang);
Items.create({ route: route + (prefix ? '-' + prefix : ''), value: req.body.value })
.then(function(item){
res.send({ item: _.pick(item, ['id', 'route', 'author_id', 'created_at']) })
})
.catch(function(){ res.sendStatus(500)});
})
.catch(function(){ res.sendStatus(500) });
generate additional characters
var chars = {
ar: { val: "اﻻبتثجحخدذرزسشصضطظعغفقكلمنهةوىي", len: 0 },
he: { val: "אבגדהוזחטיכלמנסעפצקרשת", len: 0 },
en: { val: "abcdefghijklmnopqrstuvwxyz", len: 0 }
};
_.forEach(chars, (c) => { c.len = c.val.length });
function charactersCount (current, lang) => {
if (!current) return chars[lang].val[0];
lang = lang || 'en';
var curr = current.split(''),
len = curr.length,
pointer = len,
lastIndex;
while ((lastIndex = chars[lang].val.indexOf(curr[--pointer]) + 1) >= chars[lang].len) curr[pointer] = chars[lang].val[0];
if (pointer < 0) { curr.unshift(''); pointer++; }
curr[pointer] = chars[lang].val[lastIndex];
return curr.join('');
}
so I end up with one select query and one inset query, and prevent the clashes in node's side.
and a fulltext index is not needed since the % apears only at the end of the like operater

Can I store the output of SHOW CREATE TABLE tablename into a variable?

Can I store the output of SHOW CREATE TABLE tablename into a variable?
If possible, how would I do that?
This is not possible. Although the return value looks like a standard data set, the SQL parser won't allow it in such standard queries as this:
SELECT `Create Table` INTO #foo FROM (SHOW CREATE TABLE bar);
-- results in ERROR 1064 near 'SHOW CREATE TABLE bar'
You can query the information_schema database to get the information you want though. This will provide similar output:
SELECT CONCAT(
'CREATE TABLE `',
t.TABLE_NAME,
'`(\n',
GROUP_CONCAT(
CONCAT(
' `',
c.COLUMN_NAME,
'` ',
c.COLUMN_TYPE,
' ',
IF(c.DATA_TYPE = 'varchar', CONCAT('COLLATE ', c.COLLATION_NAME, ' '), ''),
IF(c.IS_NULLABLE = 'NO', 'NOT NULL', ''),
IFNULL(CONCAT(' DEFAULT ', c.COLUMN_DEFAULT), ''),
' ',
c.EXTRA
)
SEPARATOR ',\n'
),
'\n) ENGINE=',
t.ENGINE,
' AUTO_INCREMENT=',
t.AUTO_INCREMENT,
' DEFAULT CHARSET=',
s.DEFAULT_CHARACTER_SET_NAME,
' COLLATE=',
t.TABLE_COLLATION
) AS create_statement
FROM information_schema.schemata s
INNER JOIN information_schema.tables t
ON s.SCHEMA_NAME = t.TABLE_SCHEMA
INNER JOIN information_schema.columns c
ON (c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME)
WHERE s.SCHEMA_NAME = 'mydatabase' AND t.TABLE_NAME = 'mytable';
The notable exception being key information.
You can do it with the results, with php for example:
function getCreateSQLFromTableName($table){
$sql = "SHOW CREATE TABLE $table";
echo $sql;
$res = mysql_query($sql);
if($res){
$row = mysql_fetch_assoc($res);
$createSQL = $row['Create Table'];
return $createSQL;
}
else{
echo mysql_errno() . ": " . mysql_error(). "\n";
}
}
/**
*
* Get info about table from 'SHOW CREATE TABLE'
*
* #param string $table table
* #return false|array
*/
function table_info($table, $include_fields = ['table', 'alter'])
{
if ( strlen($table) > 0 )
{
$query = "SHOW CREATE TABLE {$table}";
$result = mqc($query);
if ( $result )
{
$fields_separator_begin = ' (' . n();
$fields_separator_end = n() . ') ';
$fields_separator_item = ',' . n();
$alter_separator = ' ';
$info_data = mfa($result);
$response['table'] = trim($info_data['Table']);
$response['create'] = trim($info_data['Create Table']);
$info_data_2 = explode($fields_separator_begin, $info_data['Create Table'], 2);
$info_data_3 = explode($fields_separator_end, $info_data_2[1]); unset($info_data_2);
$fields_string = trim($info_data_3[0]);
$fields_data = explode($fields_separator_item, $fields_string);
$alter_string = trim($info_data_3[1]);
$alter_data = explode($alter_separator, $alter_string, 5);
unset($info_data_3);
$primary = trim(end($fields_data));
$response['primary'] = $primary;
$response['alter'] = [];
foreach ($alter_data as $alter_datum)
{
if ( ifound($alter_datum, '=') )
{
$alter_item_data = explode('=', $alter_datum);
$response['alter'][$alter_item_data[0]] = $alter_item_data[1];
} else
{
$response['alter'][$alter_datum] = $alter_datum;
}
}
end($fields_data);
$key = key($fields_data);
unset($fields_data[$key]);
$response['fields'] = [];
foreach ($fields_data as $field)
{
$field_data = explode(' ', trim($field), 3);
$response['fields'][] = $field_data;
}
if ( count($include_fields) > 0 )
{
$response_slice = [];
foreach ($response as $response_field => $response_data)
{
if ( in_array($response_field, $include_fields) )
{
$response_slice[$response_field] = $response_data;
}
}
return $response_slice;
} else return $response;
} else return false;
} else return false;
}
Usage:
$table_info = table_info('table_name', [])
print_r($table_info);
Array
(
[table] => caop_access
[create] => CREATE TABLE `caop_access` (
`access_id` int(11) NOT NULL AUTO_INCREMENT,
`access_title` varchar(50) NOT NULL,
`access_level` int(11) NOT NULL DEFAULT '0',
`access_desc` varchar(100) NOT NULL,
PRIMARY KEY (`access_id`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='Type of access'
[primary] => PRIMARY KEY (`access_id`)
[alter] => Array
(
[ENGINE] => MyISAM
[AUTO_INCREMENT] => 7
[DEFAULT] => DEFAULT
[CHARSET] => utf8
[COMMENT] => 'Type of access'
)
[fields] => Array
(
[0] => Array
(
[0] => `access_id`
[1] => int(11)
[2] => NOT NULL AUTO_INCREMENT
)
[1] => Array
(
[0] => `access_title`
[1] => varchar(50)
[2] => NOT NULL
)
[2] => Array
(
[0] => `access_level`
[1] => int(11)
[2] => NOT NULL DEFAULT '0'
)
[3] => Array
(
[0] => `access_desc`
[1] => varchar(100)
[2] => NOT NULL
)
)
)
Works for me...