当列的表位于另一台服务器上时,是否有办法获取列的默认定义?
我尝试直接查询import bs4, urlparse, json, requests
from os.path import basename as bn
links = [] # the relative paths to companies
data = {} # company name --> company data
base = 'http://data-interview.enigmalabs.org/'
def bs(r): # returns a beautifulsoup table object for the table in the page of the relative path
return bs4.BeautifulSoup(requests.get(urlparse.urljoin(base, r).encode()).content, 'html.parser').find('table')
for i in range(1,11):
print 'Collecting page %d' % i
# add end-point links
links += [a['href'] for a in bs('companies?page=%d' % i).findAll('a')]
for link in links:
print 'Processing %s' % link
name = bn(link)
data[name] = {}
for row in bs(link).findAll('tr'):
desc, cont = row.findAll('td')
data[name][desc.text.encode()] = cont.text.encode()
print json.dumps(data)
,但却发现diffserver.dbname.sys.default_constraints
视图使用sys.default_constraints
作为"定义"专栏,这显然不适用于另一台服务器。 (它甚至不能在不同的数据库中工作。)
例如,此查询返回"定义"中的所有NULL。列" diffserver"是与您当前使用的服务器不同的服务器。 (此查询假定链接服务器为diffserver。)
OBJECT_DEFINITION
我想要这样做的原因是只从元数据中查看表的所有列定义,除了默认约束之外,我可以成功地完成所有操作。由于上述问题,我可以得到约束 name ,但不能得到定义。这是完整查询,仅适用于上下文。
select * from diffserver.somedb.sys.default_constraints
是否有另一种方法可以从SQL 2008+中的另一台服务器获取列的默认定义? (我已经在SQL 2008和2012上尝试过了。)
更新: 基于这里的答案,我发现了另一条信息。我这样做的服务器上有十几个数据库。我运行以下查询依次替换每个数据库名称为" dbname"在查询中(IOW,如果diffserver有db1,db2和db3,我运行了三次查询,将db1,db2,db3中的每一个替换为" dbname"在查询中):
SELECT o.name,
c.column_id AS num,
c.name AS "column",
CASE
WHEN t.name IN ('char','varchar','binary','varbinary')
THEN t.name + '(' + CASE c.max_length WHEN -1 THEN 'max' ELSE CAST(c.max_length AS varchar) END + ')'
WHEN t.name = 'datetime2'
THEN t.name + '(' + CAST(c.scale AS varchar) + ')'
WHEN t.name IN ('decimal','numeric')
THEN t.name + '(' + CAST(c.precision AS varchar) + ISNULL(','+CAST(c.scale AS varchar),'') + ')'
WHEN t.name IN ('float','real')
THEN CASE WHEN c.precision <= 24 THEN 'real' ELSE 'float' END
WHEN t.name IN ('nchar','nvarchar')
THEN t.name + '(' + CASE c.max_length WHEN -1 THEN 'max' ELSE CAST(c.max_length/2 AS varchar) END + ')'
ELSE
t.name
END AS "type",
CASE c.is_nullable WHEN 1 THEN 'NULL' ELSE 'NOT NULL' END AS nulls,
ISNULL(dc.definition,'') AS "default",
CASE c.is_identity WHEN 1 THEN 'YES' ELSE '' END AS ident
FROM sys.objects o
INNER JOIN sys.columns c ON o.object_id = c.object_id
LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT JOIN sys.default_constraints dc ON c.default_object_id = dc.object_id
WHERE o.name = 'sometable'
AND o.type = 'U'
ORDER BY o.name,c.column_id
对于除一个数据库之外的每个数据库,该查询在每行的定义列中返回NULL。那个数据库不是我用户的默认数据库。它也不是我在当前服务器上的数据库。那么为什么这个数据库工作(修辞问题)呢?我还没有意识到这一点。 可能是它是服务器上安装的第一个数据库,但这是猜想。 (我相信它是第一个安装的数据库,猜想部分是&#34;第一个&#34;是什么导致它工作。)
所以,如果你碰巧选择了一个&#34;对&#34;数据库,然后使用openquery而不是直接查询似乎工作(正如它为建议的答案之一所做的那样)。但是,至少对我来说,它并不适用于服务器上的任何其他数据库。我只通过反复试验找到了一个数据库,所以它绝对不能作为一般答案。
答案 0 :(得分:0)
我只是尝试使用openquery,它在另一台服务器上运行查询,它似乎对我有用。
select *
from openquery(linkedservername, 'SELECT o.name,
c.column_id AS num,
c.name AS "column",
CASE
WHEN t.name IN (''char'',''varchar'',''binary'',''varbinary'')
THEN t.name + ''('' + CASE c.max_length WHEN -1 THEN ''max'' ELSE CAST(c.max_length AS varchar) END + '')''
WHEN t.name = ''datetime2''
THEN t.name + ''('' + CAST(c.scale AS varchar) + '')''
WHEN t.name IN (''decimal'',''numeric'')
THEN t.name + ''('' + CAST(c.precision AS varchar) + ISNULL('',''+CAST(c.scale AS varchar),'''') + '')''
WHEN t.name IN (''float'',''real'')
THEN CASE WHEN c.precision <= 24 THEN ''real'' ELSE ''float'' END
WHEN t.name IN (''nchar'',''nvarchar'')
THEN t.name + ''('' + CASE c.max_length WHEN -1 THEN ''max'' ELSE CAST(c.max_length/2 AS varchar) END + '')''
ELSE
t.name
END AS "type",
CASE c.is_nullable WHEN 1 THEN ''NULL'' ELSE ''NOT NULL'' END AS nulls,
ISNULL(dc.definition,'''') AS "default",
CASE c.is_identity WHEN 1 THEN ''YES'' ELSE '''' END AS ident
FROM sys.objects o
INNER JOIN sys.columns c ON o.object_id = c.object_id
LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT JOIN sys.default_constraints dc ON c.column_id = dc.parent_column_id
and dc.parent_object_id = c.object_id
WHERE o.type = ''U''
and o.name = ''sometable''
ORDER BY o.name,c.column_id')