J'ai une requête SQL qui interroge une énorme base de données (comme des centaines de vues/tables avec des noms difficiles à lire comme CMM-CPP-FAP-ADD) que je n'ai ni besoin ni envie de comprendre. Le résultat de cette requête doit être stocké dans une table intermédiaire pour alimenter un rapport.
Je dois créer la table intermédiaire, mais avec des centaines de vues/tables dans lesquelles creuser pour trouver les types de données représentés, je me demande s'il existe un meilleur moyen de construire cette table.
Quelqu'un peut-il me dire comment utiliser l'un des outils SQL Server 2008 pour deviner les types de données source dans ma base de données SQL 2000?
Comme exemple général, je veux savoir à partir d'une requête comme:
SELECT Auth_First_Name, Auth_Last_Name, Auth_Favorite_Number
FROM Authors
Au lieu des résultats réels, je veux savoir que:
Auth_First_Name is char(25)
Auth_Last_Name is char(50)
Auth_Favorite_Number is int
Les contraintes ne m'intéressent pas, je veux simplement connaître les types de données.
select * from information_schema.columns
pourrait vous aider à démarrer.
Vous pouvez également insérer les résultats (ou les 10 meilleurs résultats) dans une table temporaire et extraire les colonnes de la table temporaire (tant que les noms des colonnes sont tous différents).
SELECT TOP 10 *
INTO #TempTable
FROM <DataSource>
Alors utilisez:
EXEC tempdb.dbo.sp_help N'#TempTable';
ou
SELECT *
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..#TempTable');
Extrapolée à partir de la réponse d'Aaron ici .
Vous pouvez aussi utiliser...
SQL_VARIANT_PROPERTY()
... dans les cas où vous n'avez pas un accès direct aux métadonnées (par exemple, une requête de serveur lié peut-être?).
http://msdn.Microsoft.com/en-us/library/ms178550.aspx
Dans SQL Server 2005 et au-delà, il vaut mieux utiliser les vues de catalogue (sys.columns), par opposition à INFORMATION_SCHEMA. À moins que la portabilité vers d'autres plates-formes soit importante. N'oubliez pas que les vues INFORMATION_SCHEMA ne changeront pas et qu'elles manqueront progressivement d'informations sur les nouvelles fonctionnalités, etc., dans les versions successives de SQL Server.
Il y a DOIT un moyen plus facile de le faire ... Bas et voici, il y a ...!
"sp_describe_first_result_set} _" est votre ami!
Maintenant, je réalise que la question a été posée spécifiquement pour SQL Server 2000, mais je recherchais une solution similaire pour les versions ultérieures et découvris un support natif en SQL pour y parvenir.
Dans SQL Server 2012 et après cf. "sp_describe_first_result_set" - Lien vers BOL
J'avais déjà implémenté une solution utilisant une technique similaire à celle de @ Trisped above et je l'ai extraite pour implémenter l'implémentation native de SQL Server.
Si vous n'êtes pas encore sur SQL Server 2012 ou la base de données Azure SQL, voici le proc stocké que j'ai créé pour les bases de données antérieures à 2012:
CREATE PROCEDURE [fn].[GetQueryResultMetadata]
@queryText VARCHAR(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
--SET NOCOUNT ON;
PRINT @queryText;
DECLARE
@sqlToExec NVARCHAR(MAX) =
'SELECT TOP 1 * INTO #QueryMetadata FROM ('
+
@queryText
+
') T;'
+ '
SELECT
C.Name [ColumnName],
TP.Name [ColumnType],
C.max_length [MaxLength],
C.[precision] [Precision],
C.[scale] [Scale],
C.[is_nullable] IsNullable
FROM
tempdb.sys.columns C
INNER JOIN
tempdb.sys.types TP
ON
TP.system_type_id = C.system_type_id
AND
-- exclude custom types
TP.system_type_id = TP.user_type_id
WHERE
[object_id] = OBJECT_ID(N''tempdb..#QueryMetadata'');
'
EXEC sp_executesql @sqlToExec
END
SELECT COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH
FROM information_schema.columns
WHERE TABLE_NAME = 'YOUR_TABLE_NAME'
Vous pouvez utiliser des alias de colonnes pour une meilleure apparence.
Pour SQL Server 2012 et les versions ultérieures: Si vous placez la requête dans une chaîne, vous pouvez obtenir les types de données d'ensemble de résultats comme suit:
DECLARE @query nvarchar(max) = 'select 12.1 / 10.1 AS [Column1]';
EXEC sp_describe_first_result_set @query, null, 0;
Pouvez-vous vous permettre de recréer la table intermédiaire à partir de zéro chaque fois que la requête est exécutée? Si tel est le cas, vous pouvez utiliser SELECT ... INTO
syntax et laisser SQL Server s’inquiéter de la création de la table avec les types de colonne appropriés, etc.
SELECT *
INTO your_staging_table
FROM enormous_collection_of_views_tables_etc
select COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='yourTable';
Cela vous donnera tout ce qui concerne la propriété de la colonne.
SELECT * INTO TMP1
FROM ( SELECT TOP 1 /* rest of your query expression here */ );
SELECT o.name AS obj_name, TYPE_NAME(c.user_type_id) AS type_name, c.*
FROM sys.objects AS o
JOIN sys.columns AS c ON o.object_id = c.object_id
WHERE o.name = 'TMP1';
DROP TABLE TMP1;
J'utilise une simple déclaration de cas pour rendre les résultats que je peux utiliser dans les documents de spécifications techniques. Cet exemple ne contient pas toutes les conditions que vous rencontrerez avec une base de données, mais il vous fournit un bon modèle à utiliser.
SELECT
TABLE_NAME AS 'Table Name',
COLUMN_NAME AS 'Column Name',
CASE WHEN DATA_TYPE LIKE '%char'
THEN DATA_TYPE + '(' + CONVERT(VARCHAR, CHARACTER_MAXIMUM_LENGTH) + ')'
WHEN DATA_TYPE IN ('bit', 'int', 'smallint', 'date')
THEN DATA_TYPE
WHEN DATA_TYPE = 'datetime'
THEN DATA_TYPE + '(' + CONVERT(VARCHAR, DATETIME_PRECISION) + ')'
WHEN DATA_TYPE = 'float'
THEN DATA_TYPE
WHEN DATA_TYPE IN ('numeric', 'money')
THEN DATA_TYPE + '(' + CONVERT(VARCHAR, NUMERIC_PRECISION) + ', ' + CONVERT(VARCHAR, NUMERIC_PRECISION_RADIX) + ')'
END AS 'Data Type',
CASE WHEN IS_NULLABLE = 'NO'
THEN 'NOT NULL'
ELSE 'NULL'
END AS 'PK/LK/NOT NULL'
FROM INFORMATION_SCHEMA.COLUMNS
ORDER BY
TABLE_NAME, ORDINAL_POSITION
sp_describe_first_result_set
aidera à identifier les types de données de requête en analysant les types de données du premier ensemble de résultats de requête